Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
_common.py192 linesDownload Raw Back to importlib_resources
1import contextlib2import functools3import importlib4import inspect5import itertools6import os7import pathlib8import tempfile9import types10from typing import Optional, cast11 12from .abc import ResourceReader, Traversable13 14Package = types.ModuleType | str15Anchor = Package16 17 18def files(anchor: Optional[Anchor] = None) -> Traversable:19    """20    Get a Traversable resource for an anchor.21    """22    return from_package(resolve(anchor))23 24 25def get_resource_reader(package: types.ModuleType) -> Optional[ResourceReader]:26    """27    Return the package's loader if it's a ResourceReader.28    """29    # We can't use30    # a issubclass() check here because apparently abc.'s __subclasscheck__()31    # hook wants to create a weak reference to the object, but32    # zipimport.zipimporter does not support weak references, resulting in a33    # TypeError.  That seems terrible.34    spec = package.__spec__35    reader = getattr(spec.loader, 'get_resource_reader', None)  # type: ignore[union-attr]36    if reader is None:37        return None38    return reader(spec.name)  # type: ignore[union-attr]39 40 41@functools.singledispatch42def resolve(cand: Optional[Anchor]) -> types.ModuleType:43    return cast(types.ModuleType, cand)44 45 46@resolve.register47def _(cand: str) -> types.ModuleType:48    return importlib.import_module(cand)49 50 51@resolve.register52def _(cand: None) -> types.ModuleType:53    return resolve(_infer_caller().f_globals['__name__'])54 55 56def _infer_caller():57    """58    Walk the stack and find the frame of the first caller not in this module.59    """60 61    def is_this_file(frame_info):62        return frame_info.filename == stack[0].filename63 64    def is_wrapper(frame_info):65        return frame_info.function == 'wrapper'66 67    stack = inspect.stack()68    not_this_file = itertools.filterfalse(is_this_file, stack)69    # also exclude 'wrapper' due to singledispatch in the call stack70    callers = itertools.filterfalse(is_wrapper, not_this_file)71    return next(callers).frame72 73 74def _assert_spec(package: types.ModuleType) -> None:75    """76    Provide a nicer error message when package is ``__main__``77    and its ``__spec__`` is ``None``78    (https://docs.python.org/3/reference/import.html#main-spec).79    """80    if package.__spec__ is None:81        raise TypeError(82            f"Cannot access resources for '{package.__name__}' "83            "as it does not appear to correspond to an importable module (its __spec__ is None)."84        )85 86 87def from_package(package: types.ModuleType):88    """89    Return a Traversable object for the given package.90 91    """92    # deferred for performance (python/cpython#109829)93    from .future.adapters import wrap_spec94 95    _assert_spec(package)96    spec = wrap_spec(package)97    reader = spec.loader.get_resource_reader(spec.name)98    return reader.files()99 100 101@contextlib.contextmanager102def _tempfile(103    reader,104    suffix='',105    # gh-93353: Keep a reference to call os.remove() in late Python106    # finalization.107    *,108    _os_remove=os.remove,109):110    # Not using tempfile.NamedTemporaryFile as it leads to deeper 'try'111    # blocks due to the need to close the temporary file to work on Windows112    # properly.113    fd, raw_path = tempfile.mkstemp(suffix=suffix)114    try:115        try:116            os.write(fd, reader())117        finally:118            os.close(fd)119        del reader120        yield pathlib.Path(raw_path)121    finally:122        try:123            _os_remove(raw_path)124        except FileNotFoundError:125            pass126 127 128def _temp_file(path):129    return _tempfile(path.read_bytes, suffix=path.name)130 131 132def _is_present_dir(path: Traversable) -> bool:133    """134    Some Traversables implement ``is_dir()`` to raise an135    exception (i.e. ``FileNotFoundError``) when the136    directory doesn't exist. This function wraps that call137    to always return a boolean and only return True138    if there's a dir and it exists.139    """140    with contextlib.suppress(FileNotFoundError):141        return path.is_dir()142    return False143 144 145@functools.singledispatch146def as_file(path):147    """148    Given a Traversable object, return that object as a149    path on the local file system in a context manager.150    """151    return _temp_dir(path) if _is_present_dir(path) else _temp_file(path)152 153 154@as_file.register(pathlib.Path)155@contextlib.contextmanager156def _(path):157    """158    Degenerate behavior for pathlib.Path objects.159    """160    yield path161 162 163@contextlib.contextmanager164def _temp_path(dir: tempfile.TemporaryDirectory):165    """166    Wrap tempfile.TemporaryDirectory to return a pathlib object.167    """168    with dir as result:169        yield pathlib.Path(result)170 171 172@contextlib.contextmanager173def _temp_dir(path):174    """175    Given a traversable dir, recursively replicate the whole tree176    to the file system in a context manager.177    """178    assert path.is_dir()179    with _temp_path(tempfile.TemporaryDirectory()) as temp_dir:180        yield _write_contents(temp_dir, path)181 182 183def _write_contents(target, source):184    child = target.joinpath(source.name)185    if source.is_dir():186        child.mkdir()187        for item in source.iterdir():188            _write_contents(child, item)189    else:190        child.write_bytes(source.read_bytes())191    return child192 
codekingpro/portable-devtools · Team Ai