Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
_common.py211 linesDownload Raw Back to importlib_resources
1import os2import pathlib3import tempfile4import functools5import contextlib6import types7import importlib8import inspect9import warnings10import itertools11 12from typing import Union, Optional, cast13from .abc import ResourceReader, Traversable14 15Package = Union[types.ModuleType, str]16Anchor = Package17 18 19def package_to_anchor(func):20    """21    Replace 'package' parameter as 'anchor' and warn about the change.22 23    Other errors should fall through.24 25    >>> files('a', 'b')26    Traceback (most recent call last):27    TypeError: files() takes from 0 to 1 positional arguments but 2 were given28 29    Remove this compatibility in Python 3.14.30    """31    undefined = object()32 33    @functools.wraps(func)34    def wrapper(anchor=undefined, package=undefined):35        if package is not undefined:36            if anchor is not undefined:37                return func(anchor, package)38            warnings.warn(39                "First parameter to files is renamed to 'anchor'",40                DeprecationWarning,41                stacklevel=2,42            )43            return func(package)44        elif anchor is undefined:45            return func()46        return func(anchor)47 48    return wrapper49 50 51@package_to_anchor52def files(anchor: Optional[Anchor] = None) -> Traversable:53    """54    Get a Traversable resource for an anchor.55    """56    return from_package(resolve(anchor))57 58 59def get_resource_reader(package: types.ModuleType) -> Optional[ResourceReader]:60    """61    Return the package's loader if it's a ResourceReader.62    """63    # We can't use64    # a issubclass() check here because apparently abc.'s __subclasscheck__()65    # hook wants to create a weak reference to the object, but66    # zipimport.zipimporter does not support weak references, resulting in a67    # TypeError.  That seems terrible.68    spec = package.__spec__69    reader = getattr(spec.loader, 'get_resource_reader', None)  # type: ignore70    if reader is None:71        return None72    return reader(spec.name)  # type: ignore73 74 75@functools.singledispatch76def resolve(cand: Optional[Anchor]) -> types.ModuleType:77    return cast(types.ModuleType, cand)78 79 80@resolve.register81def _(cand: str) -> types.ModuleType:82    return importlib.import_module(cand)83 84 85@resolve.register86def _(cand: None) -> types.ModuleType:87    return resolve(_infer_caller().f_globals['__name__'])88 89 90def _infer_caller():91    """92    Walk the stack and find the frame of the first caller not in this module.93    """94 95    def is_this_file(frame_info):96        return frame_info.filename == __file__97 98    def is_wrapper(frame_info):99        return frame_info.function == 'wrapper'100 101    not_this_file = itertools.filterfalse(is_this_file, inspect.stack())102    # also exclude 'wrapper' due to singledispatch in the call stack103    callers = itertools.filterfalse(is_wrapper, not_this_file)104    return next(callers).frame105 106 107def from_package(package: types.ModuleType):108    """109    Return a Traversable object for the given package.110 111    """112    # deferred for performance (python/cpython#109829)113    from .future.adapters import wrap_spec114 115    spec = wrap_spec(package)116    reader = spec.loader.get_resource_reader(spec.name)117    return reader.files()118 119 120@contextlib.contextmanager121def _tempfile(122    reader,123    suffix='',124    # gh-93353: Keep a reference to call os.remove() in late Python125    # finalization.126    *,127    _os_remove=os.remove,128):129    # Not using tempfile.NamedTemporaryFile as it leads to deeper 'try'130    # blocks due to the need to close the temporary file to work on Windows131    # properly.132    fd, raw_path = tempfile.mkstemp(suffix=suffix)133    try:134        try:135            os.write(fd, reader())136        finally:137            os.close(fd)138        del reader139        yield pathlib.Path(raw_path)140    finally:141        try:142            _os_remove(raw_path)143        except FileNotFoundError:144            pass145 146 147def _temp_file(path):148    return _tempfile(path.read_bytes, suffix=path.name)149 150 151def _is_present_dir(path: Traversable) -> bool:152    """153    Some Traversables implement ``is_dir()`` to raise an154    exception (i.e. ``FileNotFoundError``) when the155    directory doesn't exist. This function wraps that call156    to always return a boolean and only return True157    if there's a dir and it exists.158    """159    with contextlib.suppress(FileNotFoundError):160        return path.is_dir()161    return False162 163 164@functools.singledispatch165def as_file(path):166    """167    Given a Traversable object, return that object as a168    path on the local file system in a context manager.169    """170    return _temp_dir(path) if _is_present_dir(path) else _temp_file(path)171 172 173@as_file.register(pathlib.Path)174@contextlib.contextmanager175def _(path):176    """177    Degenerate behavior for pathlib.Path objects.178    """179    yield path180 181 182@contextlib.contextmanager183def _temp_path(dir: tempfile.TemporaryDirectory):184    """185    Wrap tempfile.TemporyDirectory to return a pathlib object.186    """187    with dir as result:188        yield pathlib.Path(result)189 190 191@contextlib.contextmanager192def _temp_dir(path):193    """194    Given a traversable dir, recursively replicate the whole tree195    to the file system in a context manager.196    """197    assert path.is_dir()198    with _temp_path(tempfile.TemporaryDirectory()) as temp_dir:199        yield _write_contents(temp_dir, path)200 201 202def _write_contents(target, source):203    child = target.joinpath(source.name)204    if source.is_dir():205        child.mkdir()206        for item in source.iterdir():207            _write_contents(child, item)208    else:209        child.write_bytes(source.read_bytes())210    return child211 
codekingpro/portable-devtools · Team Ai