# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/90_lens.ipynb.

# %% auto 0
__all__ = ['trylen', 'aopn', 'lenn', 'hasn', 'has1', 'has2', 'has3', 'has4']

# %% ../nbs/90_lens.ipynb 4
from operator import ge
from functools import wraps, partial

from types import BuiltinFunctionType
from typing import TypeGuard
from typing import Iterable, Callable, Optional, Union

# %% ../nbs/90_lens.ipynb 5
from chck import isint, ismthdwrap

# %% ../nbs/90_lens.ipynb 6
from .atyp import Operator
from .core import make

# %% ../nbs/90_lens.ipynb 10
def trylen(a: int | Iterable, n: int = 1, op: Operator = ge) -> TypeGuard[Iterable]:
    '''Check if `op(a, n)` if a is an `int` otherwise tries `op(len(a), n)` otherwise `False`.'''
    if ismthdwrap(a): a = a()
    if isint(a): return op(a, n)
    try: return op(len(a), n)
    except: return False

# %% ../nbs/90_lens.ipynb 12
def aopn(n: int, op: Operator = ge, __fn: str = 'len') -> Callable:
    f'''Factory for the function  `def func(a): return op(len(a), {n})`.'''
    @wraps(trylen, assigned=('__doc__'))
    def wrap(a: int | Iterable) -> TypeGuard[Iterable]:
        f'''Check if `{op.__name__}(len(a), {n}) == True.'''
        return trylen(a, n, op)
    for a in ('__name__', '__qualname__'): setattr(wrap, a, f'{__fn}{op.__name__}{n}')
    return wrap

# %% ../nbs/90_lens.ipynb 15
def lenn(n: int, op: Optional[Union[BuiltinFunctionType, Callable]] = ge) -> Callable:    
    func = partial(aopn, n, op or ge, __fn='len')()
    @wraps(func, assigned=('__doc__', '__annotations__'))
    def wrap(a: int | Iterable) -> TypeGuard[Iterable]:
        f'''Check if `a` contain at least `{n}` elements.'''
        return func(a)
    return wrap

# %% ../nbs/90_lens.ipynb 18
def hasn(a, n: int = 1) -> TypeGuard[Iterable]:
    '''Check if `a` contain at least `n` elements.'''
    func = partial(lenn, n, ge, __fn='has')()
    @wraps(func, assigned=('__doc__', '__annotations__'))
    def wrap(a: int | Iterable) -> TypeGuard[Iterable]:
        f'''Check if `a` contain at least `{n}` elements.'''
        return func(a)
    return wrap(a)

# %% ../nbs/90_lens.ipynb 20
@make('__len__', guard = lenn(1))
def has1(a) -> TypeGuard[Iterable]: '''Check if `a` has at least `1` elements.'''

@make('__len__', guard = lenn(2))
def has2(a) -> TypeGuard[Iterable]: '''Check if `a` has at least `2` elements.'''

@make('__len__', guard = lenn(3))
def has3(a) -> TypeGuard[Iterable]: '''Check if `a` has at least `3` elements.'''

@make('__len__', guard = lenn(4))
def has4(a) -> TypeGuard[Iterable]: '''Check if `a` has at least `4` elements.'''
