Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
1import abc2import itertools3import os4import pathlib5from collections.abc import Iterable, Iterator6from typing import (7    Any,8    BinaryIO,9    Literal,10    NoReturn,11    Optional,12    Protocol,13    Text,14    TextIO,15    overload,16    runtime_checkable,17)18 19StrPath = str | os.PathLike[str]20 21__all__ = ["ResourceReader", "Traversable", "TraversableResources"]22 23 24class ResourceReader(metaclass=abc.ABCMeta):25    """Abstract base class for loaders to provide resource reading support."""26 27    @abc.abstractmethod28    def open_resource(self, resource: Text) -> BinaryIO:29        """Return an opened, file-like object for binary reading.30 31        The 'resource' argument is expected to represent only a file name.32        If the resource cannot be found, FileNotFoundError is raised.33        """34        # This deliberately raises FileNotFoundError instead of35        # NotImplementedError so that if this method is accidentally called,36        # it'll still do the right thing.37        raise FileNotFoundError38 39    @abc.abstractmethod40    def resource_path(self, resource: Text) -> Text:41        """Return the file system path to the specified resource.42 43        The 'resource' argument is expected to represent only a file name.44        If the resource does not exist on the file system, raise45        FileNotFoundError.46        """47        # This deliberately raises FileNotFoundError instead of48        # NotImplementedError so that if this method is accidentally called,49        # it'll still do the right thing.50        raise FileNotFoundError51 52    @abc.abstractmethod53    def is_resource(self, path: Text) -> bool:54        """Return True if the named 'path' is a resource.55 56        Files are resources, directories are not.57        """58        raise FileNotFoundError59 60    @abc.abstractmethod61    def contents(self) -> Iterable[str]:62        """Return an iterable of entries in `package`."""63        raise FileNotFoundError64 65 66class TraversalError(Exception):67    pass68 69 70@runtime_checkable71class Traversable(Protocol):72    """73    An object with a subset of pathlib.Path methods suitable for74    traversing directories and opening files.75 76    Any exceptions that occur when accessing the backing resource77    may propagate unaltered.78    """79 80    @abc.abstractmethod81    def iterdir(self) -> Iterator["Traversable"]:82        """83        Yield Traversable objects in self84        """85 86    def read_bytes(self) -> bytes:87        """88        Read contents of self as bytes89        """90        with self.open('rb') as strm:91            return strm.read()92 93    def read_text(94        self, encoding: Optional[str] = None, errors: Optional[str] = None95    ) -> str:96        """97        Read contents of self as text98        """99        with self.open(encoding=encoding, errors=errors) as strm:100            return strm.read()101 102    @abc.abstractmethod103    def is_dir(self) -> bool:104        """105        Return True if self is a directory106        """107 108    @abc.abstractmethod109    def is_file(self) -> bool:110        """111        Return True if self is a file112        """113 114    def joinpath(self, *descendants: StrPath) -> "Traversable":115        """116        Return Traversable resolved with any descendants applied.117 118        Each descendant should be a path segment relative to self119        and each may contain multiple levels separated by120        ``posixpath.sep`` (``/``).121        """122        if not descendants:123            return self124        names = itertools.chain.from_iterable(125            path.parts for path in map(pathlib.PurePosixPath, descendants)126        )127        target = next(names)128        matches = (129            traversable for traversable in self.iterdir() if traversable.name == target130        )131        try:132            match = next(matches)133        except StopIteration:134            raise TraversalError(135                "Target not found during traversal.", target, list(names)136            )137        return match.joinpath(*names)138 139    def __truediv__(self, child: StrPath) -> "Traversable":140        """141        Return Traversable child in self142        """143        return self.joinpath(child)144 145    @overload146    def open(self, mode: Literal['r'] = 'r', *args: Any, **kwargs: Any) -> TextIO: ...147 148    @overload149    def open(self, mode: Literal['rb'], *args: Any, **kwargs: Any) -> BinaryIO: ...150 151    @abc.abstractmethod152    def open(self, mode: str = 'r', *args: Any, **kwargs: Any) -> TextIO | BinaryIO:153        """154        mode may be 'r' or 'rb' to open as text or binary. Return a handle155        suitable for reading (same as pathlib.Path.open).156 157        When opening as text, accepts encoding parameters such as those158        accepted by io.TextIOWrapper.159        """160 161    @property162    @abc.abstractmethod163    def name(self) -> str:164        """165        The base name of this object without any parent references.166        """167 168 169class TraversableResources(ResourceReader):170    """171    The required interface for providing traversable172    resources.173    """174 175    @abc.abstractmethod176    def files(self) -> "Traversable":177        """Return a Traversable object for the loaded package."""178 179    def open_resource(self, resource: StrPath) -> BinaryIO:180        return self.files().joinpath(resource).open('rb')181 182    def resource_path(self, resource: Any) -> NoReturn:183        raise FileNotFoundError(resource)184 185    def is_resource(self, path: StrPath) -> bool:186        return self.files().joinpath(path).is_file()187 188    def contents(self) -> Iterator[str]:189        return (item.name for item in self.files().iterdir())190 
codekingpro/portable-devtools · Team Ai