Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
glob.py186 linesDownload Raw Back to setuptools
1"""2Filename globbing utility. Mostly a copy of `glob` from Python 3.5.3 4Changes include:5 * `yield from` and PEP3102 `*` removed.6 * Hidden files are not ignored.7"""8 9from __future__ import annotations10 11import fnmatch12import os13import re14from collections.abc import Iterable, Iterator15from typing import TYPE_CHECKING, AnyStr, overload16 17if TYPE_CHECKING:18    from _typeshed import BytesPath, StrOrBytesPath, StrPath19 20__all__ = ["glob", "iglob", "escape"]21 22 23def glob(pathname: AnyStr, recursive: bool = False) -> list[AnyStr]:24    """Return a list of paths matching a pathname pattern.25 26    The pattern may contain simple shell-style wildcards a la27    fnmatch. However, unlike fnmatch, filenames starting with a28    dot are special cases that are not matched by '*' and '?'29    patterns.30 31    If recursive is true, the pattern '**' will match any files and32    zero or more directories and subdirectories.33    """34    return list(iglob(pathname, recursive=recursive))35 36 37def iglob(pathname: AnyStr, recursive: bool = False) -> Iterator[AnyStr]:38    """Return an iterator which yields the paths matching a pathname pattern.39 40    The pattern may contain simple shell-style wildcards a la41    fnmatch. However, unlike fnmatch, filenames starting with a42    dot are special cases that are not matched by '*' and '?'43    patterns.44 45    If recursive is true, the pattern '**' will match any files and46    zero or more directories and subdirectories.47    """48    it = _iglob(pathname, recursive)49    if recursive and _isrecursive(pathname):50        s = next(it)  # skip empty string51        assert not s52    return it53 54 55def _iglob(pathname: AnyStr, recursive: bool) -> Iterator[AnyStr]:56    dirname, basename = os.path.split(pathname)57    glob_in_dir = glob2 if recursive and _isrecursive(basename) else glob158 59    if not has_magic(pathname):60        if basename:61            if os.path.lexists(pathname):62                yield pathname63        else:64            # Patterns ending with a slash should match only directories65            if os.path.isdir(dirname):66                yield pathname67        return68 69    if not dirname:70        yield from glob_in_dir(dirname, basename)71        return72    # `os.path.split()` returns the argument itself as a dirname if it is a73    # drive or UNC path.  Prevent an infinite recursion if a drive or UNC path74    # contains magic characters (i.e. r'\\?\C:').75    if dirname != pathname and has_magic(dirname):76        dirs: Iterable[AnyStr] = _iglob(dirname, recursive)77    else:78        dirs = [dirname]79    if not has_magic(basename):80        glob_in_dir = glob081    for dirname in dirs:82        for name in glob_in_dir(dirname, basename):83            yield os.path.join(dirname, name)84 85 86# These 2 helper functions non-recursively glob inside a literal directory.87# They return a list of basenames. `glob1` accepts a pattern while `glob0`88# takes a literal basename (so it only has to check for its existence).89 90 91@overload92def glob1(dirname: StrPath, pattern: str) -> list[str]: ...93@overload94def glob1(dirname: BytesPath, pattern: bytes) -> list[bytes]: ...95def glob1(dirname: StrOrBytesPath, pattern: str | bytes) -> list[str] | list[bytes]:96    if not dirname:97        if isinstance(pattern, bytes):98            dirname = os.curdir.encode('ASCII')99        else:100            dirname = os.curdir101    try:102        names = os.listdir(dirname)103    except OSError:104        return []105    # mypy false-positives: str or bytes type possibility is always kept in sync106    return fnmatch.filter(names, pattern)  # type: ignore[type-var, return-value]107 108 109def glob0(dirname, basename):110    if not basename:111        # `os.path.split()` returns an empty basename for paths ending with a112        # directory separator.  'q*x/' should match only directories.113        if os.path.isdir(dirname):114            return [basename]115    else:116        if os.path.lexists(os.path.join(dirname, basename)):117            return [basename]118    return []119 120 121# This helper function recursively yields relative pathnames inside a literal122# directory.123 124 125@overload126def glob2(dirname: StrPath, pattern: str) -> Iterator[str]: ...127@overload128def glob2(dirname: BytesPath, pattern: bytes) -> Iterator[bytes]: ...129def glob2(dirname: StrOrBytesPath, pattern: str | bytes) -> Iterator[str | bytes]:130    assert _isrecursive(pattern)131    yield pattern[:0]132    yield from _rlistdir(dirname)133 134 135# Recursively yields relative pathnames inside a literal directory.136@overload137def _rlistdir(dirname: StrPath) -> Iterator[str]: ...138@overload139def _rlistdir(dirname: BytesPath) -> Iterator[bytes]: ...140def _rlistdir(dirname: StrOrBytesPath) -> Iterator[str | bytes]:141    if not dirname:142        if isinstance(dirname, bytes):143            dirname = os.curdir.encode('ASCII')144        else:145            dirname = os.curdir146    try:147        names = os.listdir(dirname)148    except OSError:149        return150    for x in names:151        yield x152        # mypy false-positives: str or bytes type possibility is always kept in sync153        path = os.path.join(dirname, x) if dirname else x  # type: ignore[arg-type]154        for y in _rlistdir(path):155            yield os.path.join(x, y)  # type: ignore[arg-type]156 157 158magic_check = re.compile('([*?[])')159magic_check_bytes = re.compile(b'([*?[])')160 161 162def has_magic(s: str | bytes) -> bool:163    if isinstance(s, bytes):164        return magic_check_bytes.search(s) is not None165    else:166        return magic_check.search(s) is not None167 168 169def _isrecursive(pattern: str | bytes) -> bool:170    if isinstance(pattern, bytes):171        return pattern == b'**'172    else:173        return pattern == '**'174 175 176def escape(pathname):177    """Escape all special characters."""178    # Escaping is done by wrapping any of "*?[" between square brackets.179    # Metacharacters do not work in the drive part and shouldn't be escaped.180    drive, pathname = os.path.splitdrive(pathname)181    if isinstance(pathname, bytes):182        pathname = magic_check_bytes.sub(rb'[\1]', pathname)183    else:184        pathname = magic_check.sub(r'[\1]', pathname)185    return drive + pathname186 
codekingpro/portable-devtools · Team Ai