Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
__init__.py1308 linesDownload Raw Back to pathlib
1"""Object-oriented filesystem paths.2 3This module provides classes to represent abstract paths and concrete4paths with operations that have semantics appropriate for different5operating systems.6"""7 8import io9import ntpath10import operator11import os12import posixpath13import sys14from errno import *15from glob import _StringGlobber, _no_recurse_symlinks16from itertools import chain17from stat import S_ISDIR, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO18from _collections_abc import Sequence19 20try:21    import pwd22except ImportError:23    pwd = None24try:25    import grp26except ImportError:27    grp = None28 29from pathlib._os import (30    PathInfo, DirEntryInfo,31    ensure_different_files, ensure_distinct_paths,32    copyfile2, copyfileobj, magic_open, copy_info,33)34 35 36__all__ = [37    "UnsupportedOperation",38    "PurePath", "PurePosixPath", "PureWindowsPath",39    "Path", "PosixPath", "WindowsPath",40    ]41 42 43class UnsupportedOperation(NotImplementedError):44    """An exception that is raised when an unsupported operation is attempted.45    """46    pass47 48 49class _PathParents(Sequence):50    """This object provides sequence-like access to the logical ancestors51    of a path.  Don't try to construct it yourself."""52    __slots__ = ('_path', '_drv', '_root', '_tail')53 54    def __init__(self, path):55        self._path = path56        self._drv = path.drive57        self._root = path.root58        self._tail = path._tail59 60    def __len__(self):61        return len(self._tail)62 63    def __getitem__(self, idx):64        if isinstance(idx, slice):65            return tuple(self[i] for i in range(*idx.indices(len(self))))66 67        if idx >= len(self) or idx < -len(self):68            raise IndexError(idx)69        if idx < 0:70            idx += len(self)71        return self._path._from_parsed_parts(self._drv, self._root,72                                             self._tail[:-idx - 1])73 74    def __repr__(self):75        return "<{}.parents>".format(type(self._path).__name__)76 77 78class PurePath:79    """Base class for manipulating paths without I/O.80 81    PurePath represents a filesystem path and offers operations which82    don't imply any actual filesystem I/O.  Depending on your system,83    instantiating a PurePath will return either a PurePosixPath or a84    PureWindowsPath object.  You can also instantiate either of these classes85    directly, regardless of your system.86    """87 88    __slots__ = (89        # The `_raw_paths` slot stores unjoined string paths. This is set in90        # the `__init__()` method.91        '_raw_paths',92 93        # The `_drv`, `_root` and `_tail_cached` slots store parsed and94        # normalized parts of the path. They are set when any of the `drive`,95        # `root` or `_tail` properties are accessed for the first time. The96        # three-part division corresponds to the result of97        # `os.path.splitroot()`, except that the tail is further split on path98        # separators (i.e. it is a list of strings), and that the root and99        # tail are normalized.100        '_drv', '_root', '_tail_cached',101 102        # The `_str` slot stores the string representation of the path,103        # computed from the drive, root and tail when `__str__()` is called104        # for the first time. It's used to implement `_str_normcase`105        '_str',106 107        # The `_str_normcase_cached` slot stores the string path with108        # normalized case. It is set when the `_str_normcase` property is109        # accessed for the first time. It's used to implement `__eq__()`110        # `__hash__()`, and `_parts_normcase`111        '_str_normcase_cached',112 113        # The `_parts_normcase_cached` slot stores the case-normalized114        # string path after splitting on path separators. It's set when the115        # `_parts_normcase` property is accessed for the first time. It's used116        # to implement comparison methods like `__lt__()`.117        '_parts_normcase_cached',118 119        # The `_hash` slot stores the hash of the case-normalized string120        # path. It's set when `__hash__()` is called for the first time.121        '_hash',122    )123    parser = os.path124 125    def __new__(cls, *args, **kwargs):126        """Construct a PurePath from one or several strings and or existing127        PurePath objects.  The strings and path objects are combined so as128        to yield a canonicalized path, which is incorporated into the129        new PurePath object.130        """131        if cls is PurePath:132            cls = PureWindowsPath if os.name == 'nt' else PurePosixPath133        return object.__new__(cls)134 135    def __init__(self, *args):136        paths = []137        for arg in args:138            if isinstance(arg, PurePath):139                if arg.parser is not self.parser:140                    # GH-103631: Convert separators for backwards compatibility.141                    paths.append(arg.as_posix())142                else:143                    paths.extend(arg._raw_paths)144            else:145                try:146                    path = os.fspath(arg)147                except TypeError:148                    path = arg149                if not isinstance(path, str):150                    raise TypeError(151                        "argument should be a str or an os.PathLike "152                        "object where __fspath__ returns a str, "153                        f"not {type(path).__name__!r}")154                paths.append(path)155        self._raw_paths = paths156 157    def with_segments(self, *pathsegments):158        """Construct a new path object from any number of path-like objects.159        Subclasses may override this method to customize how new path objects160        are created from methods like `iterdir()`.161        """162        return type(self)(*pathsegments)163 164    def joinpath(self, *pathsegments):165        """Combine this path with one or several arguments, and return a166        new path representing either a subpath (if all arguments are relative167        paths) or a totally different path (if one of the arguments is168        anchored).169        """170        return self.with_segments(self, *pathsegments)171 172    def __truediv__(self, key):173        try:174            return self.with_segments(self, key)175        except TypeError:176            return NotImplemented177 178    def __rtruediv__(self, key):179        try:180            return self.with_segments(key, self)181        except TypeError:182            return NotImplemented183 184    def __reduce__(self):185        return self.__class__, tuple(self._raw_paths)186 187    def __repr__(self):188        return "{}({!r})".format(self.__class__.__name__, self.as_posix())189 190    def __fspath__(self):191        return str(self)192 193    def __bytes__(self):194        """Return the bytes representation of the path.  This is only195        recommended to use under Unix."""196        return os.fsencode(self)197 198    @property199    def _str_normcase(self):200        # String with normalized case, for hashing and equality checks201        try:202            return self._str_normcase_cached203        except AttributeError:204            if self.parser is posixpath:205                self._str_normcase_cached = str(self)206            else:207                self._str_normcase_cached = str(self).lower()208            return self._str_normcase_cached209 210    def __hash__(self):211        try:212            return self._hash213        except AttributeError:214            self._hash = hash(self._str_normcase)215            return self._hash216 217    def __eq__(self, other):218        if not isinstance(other, PurePath):219            return NotImplemented220        return self._str_normcase == other._str_normcase and self.parser is other.parser221 222    @property223    def _parts_normcase(self):224        # Cached parts with normalized case, for comparisons.225        try:226            return self._parts_normcase_cached227        except AttributeError:228            self._parts_normcase_cached = self._str_normcase.split(self.parser.sep)229            return self._parts_normcase_cached230 231    def __lt__(self, other):232        if not isinstance(other, PurePath) or self.parser is not other.parser:233            return NotImplemented234        return self._parts_normcase < other._parts_normcase235 236    def __le__(self, other):237        if not isinstance(other, PurePath) or self.parser is not other.parser:238            return NotImplemented239        return self._parts_normcase <= other._parts_normcase240 241    def __gt__(self, other):242        if not isinstance(other, PurePath) or self.parser is not other.parser:243            return NotImplemented244        return self._parts_normcase > other._parts_normcase245 246    def __ge__(self, other):247        if not isinstance(other, PurePath) or self.parser is not other.parser:248            return NotImplemented249        return self._parts_normcase >= other._parts_normcase250 251    def __str__(self):252        """Return the string representation of the path, suitable for253        passing to system calls."""254        try:255            return self._str256        except AttributeError:257            self._str = self._format_parsed_parts(self.drive, self.root,258                                                  self._tail) or '.'259            return self._str260 261    @classmethod262    def _format_parsed_parts(cls, drv, root, tail):263        if drv or root:264            return drv + root + cls.parser.sep.join(tail)265        elif tail and cls.parser.splitdrive(tail[0])[0]:266            tail = ['.'] + tail267        return cls.parser.sep.join(tail)268 269    def _from_parsed_parts(self, drv, root, tail):270        path = self._from_parsed_string(self._format_parsed_parts(drv, root, tail))271        path._drv = drv272        path._root = root273        path._tail_cached = tail274        return path275 276    def _from_parsed_string(self, path_str):277        path = self.with_segments(path_str)278        path._str = path_str or '.'279        return path280 281    @classmethod282    def _parse_path(cls, path):283        if not path:284            return '', '', []285        sep = cls.parser.sep286        altsep = cls.parser.altsep287        if altsep:288            path = path.replace(altsep, sep)289        drv, root, rel = cls.parser.splitroot(path)290        if not root and drv.startswith(sep) and not drv.endswith(sep):291            drv_parts = drv.split(sep)292            if len(drv_parts) == 4 and drv_parts[2] not in '?.':293                # e.g. //server/share294                root = sep295            elif len(drv_parts) == 6:296                # e.g. //?/unc/server/share297                root = sep298        return drv, root, [x for x in rel.split(sep) if x and x != '.']299 300    @classmethod301    def _parse_pattern(cls, pattern):302        """Parse a glob pattern to a list of parts. This is much like303        _parse_path, except:304 305        - Rather than normalizing and returning the drive and root, we raise306          NotImplementedError if either are present.307        - If the path has no real parts, we raise ValueError.308        - If the path ends in a slash, then a final empty part is added.309        """310        drv, root, rel = cls.parser.splitroot(pattern)311        if root or drv:312            raise NotImplementedError("Non-relative patterns are unsupported")313        sep = cls.parser.sep314        altsep = cls.parser.altsep315        if altsep:316            rel = rel.replace(altsep, sep)317        parts = [x for x in rel.split(sep) if x and x != '.']318        if not parts:319            raise ValueError(f"Unacceptable pattern: {str(pattern)!r}")320        elif rel.endswith(sep):321            # GH-65238: preserve trailing slash in glob patterns.322            parts.append('')323        return parts324 325    def as_posix(self):326        """Return the string representation of the path with forward (/)327        slashes."""328        return str(self).replace(self.parser.sep, '/')329 330    @property331    def _raw_path(self):332        paths = self._raw_paths333        if len(paths) == 1:334            return paths[0]335        elif paths:336            # Join path segments from the initializer.337            return self.parser.join(*paths)338        else:339            return ''340 341    @property342    def drive(self):343        """The drive prefix (letter or UNC path), if any."""344        try:345            return self._drv346        except AttributeError:347            self._drv, self._root, self._tail_cached = self._parse_path(self._raw_path)348            return self._drv349 350    @property351    def root(self):352        """The root of the path, if any."""353        try:354            return self._root355        except AttributeError:356            self._drv, self._root, self._tail_cached = self._parse_path(self._raw_path)357            return self._root358 359    @property360    def _tail(self):361        try:362            return self._tail_cached363        except AttributeError:364            self._drv, self._root, self._tail_cached = self._parse_path(self._raw_path)365            return self._tail_cached366 367    @property368    def anchor(self):369        """The concatenation of the drive and root, or ''."""370        return self.drive + self.root371 372    @property373    def parts(self):374        """An object providing sequence-like access to the375        components in the filesystem path."""376        if self.drive or self.root:377            return (self.drive + self.root,) + tuple(self._tail)378        else:379            return tuple(self._tail)380 381    @property382    def parent(self):383        """The logical parent of the path."""384        drv = self.drive385        root = self.root386        tail = self._tail387        if not tail:388            return self389        return self._from_parsed_parts(drv, root, tail[:-1])390 391    @property392    def parents(self):393        """A sequence of this path's logical parents."""394        # The value of this property should not be cached on the path object,395        # as doing so would introduce a reference cycle.396        return _PathParents(self)397 398    @property399    def name(self):400        """The final path component, if any."""401        tail = self._tail402        if not tail:403            return ''404        return tail[-1]405 406    def with_name(self, name):407        """Return a new path with the file name changed."""408        p = self.parser409        if not name or p.sep in name or (p.altsep and p.altsep in name) or name == '.':410            raise ValueError(f"Invalid name {name!r}")411        tail = self._tail.copy()412        if not tail:413            raise ValueError(f"{self!r} has an empty name")414        tail[-1] = name415        return self._from_parsed_parts(self.drive, self.root, tail)416 417    def with_stem(self, stem):418        """Return a new path with the stem changed."""419        suffix = self.suffix420        if not suffix:421            return self.with_name(stem)422        elif not stem:423            # If the suffix is non-empty, we can't make the stem empty.424            raise ValueError(f"{self!r} has a non-empty suffix")425        else:426            return self.with_name(stem + suffix)427 428    def with_suffix(self, suffix):429        """Return a new path with the file suffix changed.  If the path430        has no suffix, add given suffix.  If the given suffix is an empty431        string, remove the suffix from the path.432        """433        stem = self.stem434        if not stem:435            # If the stem is empty, we can't make the suffix non-empty.436            raise ValueError(f"{self!r} has an empty name")437        elif suffix and not suffix.startswith('.'):438            raise ValueError(f"Invalid suffix {suffix!r}")439        else:440            return self.with_name(stem + suffix)441 442    @property443    def stem(self):444        """The final path component, minus its last suffix."""445        name = self.name446        i = name.rfind('.')447        if i != -1:448            stem = name[:i]449            # Stem must contain at least one non-dot character.450            if stem.lstrip('.'):451                return stem452        return name453 454    @property455    def suffix(self):456        """457        The final component's last suffix, if any.458 459        This includes the leading period. For example: '.txt'460        """461        name = self.name.lstrip('.')462        i = name.rfind('.')463        if i != -1:464            return name[i:]465        return ''466 467    @property468    def suffixes(self):469        """470        A list of the final component's suffixes, if any.471 472        These include the leading periods. For example: ['.tar', '.gz']473        """474        return ['.' + ext for ext in self.name.lstrip('.').split('.')[1:]]475 476    def relative_to(self, other, *, walk_up=False):477        """Return the relative path to another path identified by the passed478        arguments.  If the operation is not possible (because this is not479        related to the other path), raise ValueError.480 481        The *walk_up* parameter controls whether `..` may be used to resolve482        the path.483        """484        if not hasattr(other, 'with_segments'):485            other = self.with_segments(other)486        for step, path in enumerate(chain([other], other.parents)):487            if path == self or path in self.parents:488                break489            elif not walk_up:490                raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}")491            elif path.name == '..':492                raise ValueError(f"'..' segment in {str(other)!r} cannot be walked")493        else:494            raise ValueError(f"{str(self)!r} and {str(other)!r} have different anchors")495        parts = ['..'] * step + self._tail[len(path._tail):]496        return self._from_parsed_parts('', '', parts)497 498    def is_relative_to(self, other):499        """Return True if the path is relative to another path or False.500        """501        if not hasattr(other, 'with_segments'):502            other = self.with_segments(other)503        return other == self or other in self.parents504 505    def is_absolute(self):506        """True if the path is absolute (has both a root and, if applicable,507        a drive)."""508        if self.parser is posixpath:509            # Optimization: work with raw paths on POSIX.510            for path in self._raw_paths:511                if path.startswith('/'):512                    return True513            return False514        return self.parser.isabs(self)515 516    def is_reserved(self):517        """Return True if the path contains one of the special names reserved518        by the system, if any."""519        import warnings520        msg = ("pathlib.PurePath.is_reserved() is deprecated and scheduled "521               "for removal in Python 3.15. Use os.path.isreserved() to "522               "detect reserved paths on Windows.")523        warnings._deprecated("pathlib.PurePath.is_reserved", msg, remove=(3, 15))524        if self.parser is ntpath:525            return self.parser.isreserved(self)526        return False527 528    def as_uri(self):529        """Return the path as a URI."""530        import warnings531        msg = ("pathlib.PurePath.as_uri() is deprecated and scheduled "532               "for removal in Python 3.19. Use pathlib.Path.as_uri().")533        warnings._deprecated("pathlib.PurePath.as_uri", msg, remove=(3, 19))534        if not self.is_absolute():535            raise ValueError("relative path can't be expressed as a file URI")536 537        drive = self.drive538        if len(drive) == 2 and drive[1] == ':':539            # It's a path on a local drive => 'file:///c:/a/b'540            prefix = 'file:///' + drive541            path = self.as_posix()[2:]542        elif drive:543            # It's a path on a network drive => 'file://host/share/a/b'544            prefix = 'file:'545            path = self.as_posix()546        else:547            # It's a posix path => 'file:///etc/hosts'548            prefix = 'file://'549            path = str(self)550        from urllib.parse import quote_from_bytes551        return prefix + quote_from_bytes(os.fsencode(path))552 553    def full_match(self, pattern, *, case_sensitive=None):554        """555        Return True if this path matches the given glob-style pattern. The556        pattern is matched against the entire path.557        """558        if not hasattr(pattern, 'with_segments'):559            pattern = self.with_segments(pattern)560        if case_sensitive is None:561            case_sensitive = self.parser is posixpath562 563        # The string representation of an empty path is a single dot ('.'). Empty564        # paths shouldn't match wildcards, so we change it to the empty string.565        path = str(self) if self.parts else ''566        pattern = str(pattern) if pattern.parts else ''567        globber = _StringGlobber(self.parser.sep, case_sensitive, recursive=True)568        return globber.compile(pattern)(path) is not None569 570    def match(self, path_pattern, *, case_sensitive=None):571        """572        Return True if this path matches the given pattern. If the pattern is573        relative, matching is done from the right; otherwise, the entire path574        is matched. The recursive wildcard '**' is *not* supported by this575        method.576        """577        if not hasattr(path_pattern, 'with_segments'):578            path_pattern = self.with_segments(path_pattern)579        if case_sensitive is None:580            case_sensitive = self.parser is posixpath581        path_parts = self.parts[::-1]582        pattern_parts = path_pattern.parts[::-1]583        if not pattern_parts:584            raise ValueError("empty pattern")585        if len(path_parts) < len(pattern_parts):586            return False587        if len(path_parts) > len(pattern_parts) and path_pattern.anchor:588            return False589        globber = _StringGlobber(self.parser.sep, case_sensitive)590        for path_part, pattern_part in zip(path_parts, pattern_parts):591            match = globber.compile(pattern_part)592            if match(path_part) is None:593                return False594        return True595 596# Subclassing os.PathLike makes isinstance() checks slower,597# which in turn makes Path construction slower. Register instead!598os.PathLike.register(PurePath)599 600 601class PurePosixPath(PurePath):602    """PurePath subclass for non-Windows systems.603 604    On a POSIX system, instantiating a PurePath should return this object.605    However, you can also instantiate it directly on any system.606    """607    parser = posixpath608    __slots__ = ()609 610 611class PureWindowsPath(PurePath):612    """PurePath subclass for Windows systems.613 614    On a Windows system, instantiating a PurePath should return this object.615    However, you can also instantiate it directly on any system.616    """617    parser = ntpath618    __slots__ = ()619 620 621class Path(PurePath):622    """PurePath subclass that can make system calls.623 624    Path represents a filesystem path but unlike PurePath, also offers625    methods to do system calls on path objects. Depending on your system,626    instantiating a Path will return either a PosixPath or a WindowsPath627    object. You can also instantiate a PosixPath or WindowsPath directly,628    but cannot instantiate a WindowsPath on a POSIX system or vice versa.629    """630    __slots__ = ('_info',)631 632    def __new__(cls, *args, **kwargs):633        if cls is Path:634            cls = WindowsPath if os.name == 'nt' else PosixPath635        return object.__new__(cls)636 637    @property638    def info(self):639        """640        A PathInfo object that exposes the file type and other file attributes641        of this path.642        """643        try:644            return self._info645        except AttributeError:646            self._info = PathInfo(self)647            return self._info648 649    def stat(self, *, follow_symlinks=True):650        """651        Return the result of the stat() system call on this path, like652        os.stat() does.653        """654        return os.stat(self, follow_symlinks=follow_symlinks)655 656    def lstat(self):657        """658        Like stat(), except if the path points to a symlink, the symlink's659        status information is returned, rather than its target's.660        """661        return os.lstat(self)662 663    def exists(self, *, follow_symlinks=True):664        """665        Whether this path exists.666 667        This method normally follows symlinks; to check whether a symlink exists,668        add the argument follow_symlinks=False.669        """670        if follow_symlinks:671            return os.path.exists(self)672        return os.path.lexists(self)673 674    def is_dir(self, *, follow_symlinks=True):675        """676        Whether this path is a directory.677        """678        if follow_symlinks:679            return os.path.isdir(self)680        try:681            return S_ISDIR(self.stat(follow_symlinks=follow_symlinks).st_mode)682        except (OSError, ValueError):683            return False684 685    def is_file(self, *, follow_symlinks=True):686        """687        Whether this path is a regular file (also True for symlinks pointing688        to regular files).689        """690        if follow_symlinks:691            return os.path.isfile(self)692        try:693            return S_ISREG(self.stat(follow_symlinks=follow_symlinks).st_mode)694        except (OSError, ValueError):695            return False696 697    def is_mount(self):698        """699        Check if this path is a mount point700        """701        return os.path.ismount(self)702 703    def is_symlink(self):704        """705        Whether this path is a symbolic link.706        """707        return os.path.islink(self)708 709    def is_junction(self):710        """711        Whether this path is a junction.712        """713        return os.path.isjunction(self)714 715    def is_block_device(self):716        """717        Whether this path is a block device.718        """719        try:720            return S_ISBLK(self.stat().st_mode)721        except (OSError, ValueError):722            return False723 724    def is_char_device(self):725        """726        Whether this path is a character device.727        """728        try:729            return S_ISCHR(self.stat().st_mode)730        except (OSError, ValueError):731            return False732 733    def is_fifo(self):734        """735        Whether this path is a FIFO.736        """737        try:738            return S_ISFIFO(self.stat().st_mode)739        except (OSError, ValueError):740            return False741 742    def is_socket(self):743        """744        Whether this path is a socket.745        """746        try:747            return S_ISSOCK(self.stat().st_mode)748        except (OSError, ValueError):749            return False750 751    def samefile(self, other_path):752        """Return whether other_path is the same or not as this file753        (as returned by os.path.samefile()).754        """755        st = self.stat()756        try:757            other_st = other_path.stat()758        except AttributeError:759            other_st = self.with_segments(other_path).stat()760        return (st.st_ino == other_st.st_ino and761                st.st_dev == other_st.st_dev)762 763    def open(self, mode='r', buffering=-1, encoding=None,764             errors=None, newline=None):765        """766        Open the file pointed to by this path and return a file object, as767        the built-in open() function does.768        """769        if "b" not in mode:770            encoding = io.text_encoding(encoding)771        return io.open(self, mode, buffering, encoding, errors, newline)772 773    def read_bytes(self):774        """775        Open the file in bytes mode, read it, and close the file.776        """777        with self.open(mode='rb', buffering=0) as f:778            return f.read()779 780    def read_text(self, encoding=None, errors=None, newline=None):781        """782        Open the file in text mode, read it, and close the file.783        """784        # Call io.text_encoding() here to ensure any warning is raised at an785        # appropriate stack level.786        encoding = io.text_encoding(encoding)787        with self.open(mode='r', encoding=encoding, errors=errors, newline=newline) as f:788            return f.read()789 790    def write_bytes(self, data):791        """792        Open the file in bytes mode, write to it, and close the file.793        """794        # type-check for the buffer interface before truncating the file795        view = memoryview(data)796        with self.open(mode='wb') as f:797            return f.write(view)798 799    def write_text(self, data, encoding=None, errors=None, newline=None):800        """801        Open the file in text mode, write to it, and close the file.802        """803        # Call io.text_encoding() here to ensure any warning is raised at an804        # appropriate stack level.805        encoding = io.text_encoding(encoding)806        if not isinstance(data, str):807            raise TypeError('data must be str, not %s' %808                            data.__class__.__name__)809        with self.open(mode='w', encoding=encoding, errors=errors, newline=newline) as f:810            return f.write(data)811 812    _remove_leading_dot = operator.itemgetter(slice(2, None))813    _remove_trailing_slash = operator.itemgetter(slice(-1))814 815    def _filter_trailing_slash(self, paths):816        sep = self.parser.sep817        anchor_len = len(self.anchor)818        for path_str in paths:819            if len(path_str) > anchor_len and path_str[-1] == sep:820                path_str = path_str[:-1]821            yield path_str822 823    def _from_dir_entry(self, dir_entry, path_str):824        path = self.with_segments(path_str)825        path._str = path_str826        path._info = DirEntryInfo(dir_entry)827        return path828 829    def iterdir(self):830        """Yield path objects of the directory contents.831 832        The children are yielded in arbitrary order, and the833        special entries '.' and '..' are not included.834        """835        root_dir = str(self)836        with os.scandir(root_dir) as scandir_it:837            entries = list(scandir_it)838        if root_dir == '.':839            return (self._from_dir_entry(e, e.name) for e in entries)840        else:841            return (self._from_dir_entry(e, e.path) for e in entries)842 843    def glob(self, pattern, *, case_sensitive=None, recurse_symlinks=False):844        """Iterate over this subtree and yield all existing files (of any845        kind, including directories) matching the given relative pattern.846        """847        sys.audit("pathlib.Path.glob", self, pattern)848        if case_sensitive is None:849            case_sensitive = self.parser is posixpath850            case_pedantic = False851        else:852            # The user has expressed a case sensitivity choice, but we don't853            # know the case sensitivity of the underlying filesystem, so we854            # must use scandir() for everything, including non-wildcard parts.855            case_pedantic = True856        parts = self._parse_pattern(pattern)857        recursive = True if recurse_symlinks else _no_recurse_symlinks858        globber = _StringGlobber(self.parser.sep, case_sensitive, case_pedantic, recursive)859        select = globber.selector(parts[::-1])860        root = str(self)861        paths = select(self.parser.join(root, ''))862 863        # Normalize results864        if root == '.':865            paths = map(self._remove_leading_dot, paths)866        if parts[-1] == '':867            paths = map(self._remove_trailing_slash, paths)868        elif parts[-1] == '**':869            paths = self._filter_trailing_slash(paths)870        paths = map(self._from_parsed_string, paths)871        return paths872 873    def rglob(self, pattern, *, case_sensitive=None, recurse_symlinks=False):874        """Recursively yield all existing files (of any kind, including875        directories) matching the given relative pattern, anywhere in876        this subtree.877        """878        sys.audit("pathlib.Path.rglob", self, pattern)879        pattern = self.parser.join('**', pattern)880        return self.glob(pattern, case_sensitive=case_sensitive, recurse_symlinks=recurse_symlinks)881 882    def walk(self, top_down=True, on_error=None, follow_symlinks=False):883        """Walk the directory tree from this directory, similar to os.walk()."""884        sys.audit("pathlib.Path.walk", self, on_error, follow_symlinks)885        root_dir = str(self)886        if not follow_symlinks:887            follow_symlinks = os._walk_symlinks_as_files888        results = os.walk(root_dir, top_down, on_error, follow_symlinks)889        for path_str, dirnames, filenames in results:890            if root_dir == '.':891                path_str = path_str[2:]892            yield self._from_parsed_string(path_str), dirnames, filenames893 894    def absolute(self):895        """Return an absolute version of this path896        No normalization or symlink resolution is performed.897 898        Use resolve() to resolve symlinks and remove '..' segments.899        """900        if self.is_absolute():901            return self902        if self.root:903            drive = os.path.splitroot(os.getcwd())[0]904            return self._from_parsed_parts(drive, self.root, self._tail)905        if self.drive:906            # There is a CWD on each drive-letter drive.907            cwd = os.path.abspath(self.drive)908        else:909            cwd = os.getcwd()910        if not self._tail:911            # Fast path for "empty" paths, e.g. Path("."), Path("") or Path().912            # We pass only one argument to with_segments() to avoid the cost913            # of joining, and we exploit the fact that getcwd() returns a914            # fully-normalized string by storing it in _str. This is used to915            # implement Path.cwd().916            return self._from_parsed_string(cwd)917        drive, root, rel = os.path.splitroot(cwd)918        if not rel:919            return self._from_parsed_parts(drive, root, self._tail)920        tail = rel.split(self.parser.sep)921        tail.extend(self._tail)922        return self._from_parsed_parts(drive, root, tail)923 924    @classmethod925    def cwd(cls):926        """Return a new path pointing to the current working directory."""927        cwd = os.getcwd()928        path = cls(cwd)929        path._str = cwd  # getcwd() returns a normalized path930        return path931 932    def resolve(self, strict=False):933        """934        Make the path absolute, resolving all symlinks on the way and also935        normalizing it.936        """937 938        return self.with_segments(os.path.realpath(self, strict=strict))939 940    if pwd:941        def owner(self, *, follow_symlinks=True):942            """943            Return the login name of the file owner.944            """945            uid = self.stat(follow_symlinks=follow_symlinks).st_uid946            return pwd.getpwuid(uid).pw_name947    else:948        def owner(self, *, follow_symlinks=True):949            """950            Return the login name of the file owner.951            """952            f = f"{type(self).__name__}.owner()"953            raise UnsupportedOperation(f"{f} is unsupported on this system")954 955    if grp:956        def group(self, *, follow_symlinks=True):957            """958            Return the group name of the file gid.959            """960            gid = self.stat(follow_symlinks=follow_symlinks).st_gid961            return grp.getgrgid(gid).gr_name962    else:963        def group(self, *, follow_symlinks=True):964            """965            Return the group name of the file gid.966            """967            f = f"{type(self).__name__}.group()"968            raise UnsupportedOperation(f"{f} is unsupported on this system")969 970    if hasattr(os, "readlink"):971        def readlink(self):972            """973            Return the path to which the symbolic link points.974            """975            return self.with_segments(os.readlink(self))976    else:977        def readlink(self):978            """979            Return the path to which the symbolic link points.980            """981            f = f"{type(self).__name__}.readlink()"982            raise UnsupportedOperation(f"{f} is unsupported on this system")983 984    def touch(self, mode=0o666, exist_ok=True):985        """986        Create this file with the given access mode, if it doesn't exist.987        """988 989        if exist_ok:990            # First try to bump modification time991            # Implementation note: GNU touch uses the UTIME_NOW option of992            # the utimensat() / futimens() functions.993            try:994                os.utime(self, None)995            except OSError:996                # Avoid exception chaining997                pass998            else:999                return1000        flags = os.O_CREAT | os.O_WRONLY1001        if not exist_ok:1002            flags |= os.O_EXCL1003        fd = os.open(self, flags, mode)1004        os.close(fd)1005 1006    def mkdir(self, mode=0o777, parents=False, exist_ok=False):1007        """1008        Create a new directory at this given path.1009        """1010        try:1011            os.mkdir(self, mode)1012        except FileNotFoundError:1013            if not parents or self.parent == self:1014                raise1015            self.parent.mkdir(parents=True, exist_ok=True)1016            self.mkdir(mode, parents=False, exist_ok=exist_ok)1017        except OSError:1018            # Cannot rely on checking for EEXIST, since the operating system1019            # could give priority to other errors like EACCES or EROFS1020            if not exist_ok or not self.is_dir():1021                raise1022 1023    def chmod(self, mode, *, follow_symlinks=True):1024        """1025        Change the permissions of the path, like os.chmod().1026        """1027        os.chmod(self, mode, follow_symlinks=follow_symlinks)1028 1029    def lchmod(self, mode):1030        """1031        Like chmod(), except if the path points to a symlink, the symlink's1032        permissions are changed, rather than its target's.1033        """1034        self.chmod(mode, follow_symlinks=False)1035 1036    def unlink(self, missing_ok=False):1037        """1038        Remove this file or link.1039        If the path is a directory, use rmdir() instead.1040        """1041        try:1042            os.unlink(self)1043        except FileNotFoundError:1044            if not missing_ok:1045                raise1046 1047    def rmdir(self):1048        """1049        Remove this directory.  The directory must be empty.1050        """1051        os.rmdir(self)1052 1053    def _delete(self):1054        """1055        Delete this file or directory (including all sub-directories).1056        """1057        if self.is_symlink() or self.is_junction():1058            self.unlink()1059        elif self.is_dir():1060            # Lazy import to improve module import time1061            import shutil1062            shutil.rmtree(self)1063        else:1064            self.unlink()1065 1066    def rename(self, target):1067        """1068        Rename this path to the target path.1069 1070        The target path may be absolute or relative. Relative paths are1071        interpreted relative to the current working directory, *not* the1072        directory of the Path object.1073 1074        Returns the new Path instance pointing to the target path.1075        """1076        os.rename(self, target)1077        if not hasattr(target, 'with_segments'):1078            target = self.with_segments(target)1079        return target1080 1081    def replace(self, target):1082        """1083        Rename this path to the target path, overwriting if that path exists.1084 1085        The target path may be absolute or relative. Relative paths are1086        interpreted relative to the current working directory, *not* the1087        directory of the Path object.1088 1089        Returns the new Path instance pointing to the target path.1090        """1091        os.replace(self, target)1092        if not hasattr(target, 'with_segments'):1093            target = self.with_segments(target)1094        return target1095 1096    def copy(self, target, **kwargs):1097        """1098        Recursively copy this file or directory tree to the given destination.1099        """1100        if not hasattr(target, 'with_segments'):1101            target = self.with_segments(target)1102        ensure_distinct_paths(self, target)1103        target._copy_from(self, **kwargs)1104        return target.joinpath()  # Empty join to ensure fresh metadata.1105 1106    def copy_into(self, target_dir, **kwargs):1107        """1108        Copy this file or directory tree into the given existing directory.1109        """1110        name = self.name1111        if not name:1112            raise ValueError(f"{self!r} has an empty name")1113        elif hasattr(target_dir, 'with_segments'):1114            target = target_dir / name1115        else:1116            target = self.with_segments(target_dir, name)1117        return self.copy(target, **kwargs)1118 1119    def _copy_from(self, source, follow_symlinks=True, preserve_metadata=False):1120        """1121        Recursively copy the given path to this path.1122        """1123        if not follow_symlinks and source.info.is_symlink():1124            self._copy_from_symlink(source, preserve_metadata)1125        elif source.info.is_dir():1126            children = source.iterdir()1127            os.mkdir(self)1128            for child in children:1129                self.joinpath(child.name)._copy_from(1130                    child, follow_symlinks, preserve_metadata)1131            if preserve_metadata:1132                copy_info(source.info, self)1133        else:1134            self._copy_from_file(source, preserve_metadata)1135 1136    def _copy_from_file(self, source, preserve_metadata=False):1137        ensure_different_files(source, self)1138        with magic_open(source, 'rb') as source_f:1139            with open(self, 'wb') as target_f:1140                copyfileobj(source_f, target_f)1141        if preserve_metadata:1142            copy_info(source.info, self)1143 1144    if copyfile2:1145        # Use fast OS routine for local file copying where available.1146        _copy_from_file_fallback = _copy_from_file1147        def _copy_from_file(self, source, preserve_metadata=False):1148            try:1149                source = os.fspath(source)1150            except TypeError:1151                pass1152            else:1153                copyfile2(source, str(self))1154                return1155            self._copy_from_file_fallback(source, preserve_metadata)1156 1157    if os.name == 'nt':1158        # If a directory-symlink is copied *before* its target, then1159        # os.symlink() incorrectly creates a file-symlink on Windows. Avoid1160        # this by passing *target_is_dir* to os.symlink() on Windows.1161        def _copy_from_symlink(self, source, preserve_metadata=False):1162            os.symlink(str(source.readlink()), self, source.info.is_dir())1163            if preserve_metadata:1164                copy_info(source.info, self, follow_symlinks=False)1165    else:1166        def _copy_from_symlink(self, source, preserve_metadata=False):1167            os.symlink(str(source.readlink()), self)1168            if preserve_metadata:1169                copy_info(source.info, self, follow_symlinks=False)1170 1171    def move(self, target):1172        """1173        Recursively move this file or directory tree to the given destination.1174        """1175        # Use os.replace() if the target is os.PathLike and on the same FS.1176        try:1177            target = self.with_segments(target)1178        except TypeError:1179            pass1180        else:1181            ensure_different_files(self, target)1182            try:1183                os.replace(self, target)1184            except OSError as err:1185                if err.errno != EXDEV:1186                    raise1187            else:1188                return target.joinpath()  # Empty join to ensure fresh metadata.1189        # Fall back to copy+delete.1190        target = self.copy(target, follow_symlinks=False, preserve_metadata=True)1191        self._delete()1192        return target1193 1194    def move_into(self, target_dir):1195        """1196        Move this file or directory tree into the given existing directory.1197        """1198        name = self.name1199        if not name:1200            raise ValueError(f"{self!r} has an empty name")

Showing the first 1,200 of 1308 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai