# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/04_wrap.ipynb.

# %% auto 0
__all__ = ['vanilla', 'isguard', 'guardname', 'guarddocs', 'guardanns', 'setwrapattrs', 'makeguard', 'wrapguard', 'decoguard']

# %% ../nbs/04_wrap.ipynb 4
from functools import wraps

from typing import TypeGuard
from typing import Any, Type

# %% ../nbs/04_wrap.ipynb 5
from .atyp import G, P, TypeDesc, GuardFunc

# %% ../nbs/04_wrap.ipynb 7
def guardname(cls: G):
    return f'is{cls.__name__.lower()}'

def guarddocs(cls: G) -> str:
    return f'''Check if `x` is a `{cls.__name__}`.'''

def guardanns(cls: G) -> dict:
    return {'x': 'typing.Any', 'return': TypeGuard[Type[cls]]}

def setwrapattrs(
    call: GuardFunc, cls: G,
    docsfn: TypeDesc = guarddocs,
    namefn: TypeDesc = guardname,
    annsfn: TypeDesc = guardanns,
) -> GuardFunc:
    # Update docstring
    call.__doc__ = call.__doc__ or docsfn(cls)    
    # Update name
    call.__name__ = namefn(cls)
    # Update annotations
    call.__annotations__ = annsfn(cls)
    return call

# %% ../nbs/04_wrap.ipynb 9
def makeguard(cls: G) -> GuardFunc:
    def guard(x: Any) -> TypeGuard[cls]:
        f'''Check if `x` is a `{cls.__name__}`.'''        
        return isinstance(x, cls)
    guard = setwrapattrs(guard, cls)
    return guard

def wrapguard(cls: G, call: GuardFunc) -> GuardFunc:
    @wraps(call)
    def wrapper(x: Any, *args: P.args, **kwargs: P.kwargs) -> TypeGuard[Type[cls]]:
        f'''Check if `x` is a `{cls.__name__}`.'''
        res = None
        if kwargs.get('__call_wrapped__', True): res = call(x)
        if kwargs.get('__pass_result__', False): x = res
        return isinstance(x, cls)
        
    for mthd in (wrapper, call): mthd = setwrapattrs(mthd, cls)
    return wrapper

# %% ../nbs/04_wrap.ipynb 11
def decoguard(cls: G) -> GuardFunc:
    '''Automatically adds a type guard and docstring to a function.'''
    def decorator(call: GuardFunc) -> GuardFunc:
        return wrapguard(cls, call)
    return decorator

# %% ../nbs/04_wrap.ipynb 13
vanilla = makeguard
isguard = decoguard
