# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_core.ipynb.

# %% auto 0
__all__ = ['charjoin', 'dotstr', 'pkgstr', 'modstr', 'dostar', 'getmods', 'getall', 'getalls', 'fromstar', 'fromstars', 'frommod',
           'frommods', 'expose']

# %% ../nbs/00_core.ipynb 6
from importlib import import_module
from itertools import chain

# %% ../nbs/00_core.ipynb 8
from types import ModuleType

# %% ../nbs/00_core.ipynb 10
#| export


# %% ../nbs/00_core.ipynb 12
from nchr import U1, DOT
from nlit import __ALL__, __MODULE__
from chck import isstr
from atup import argtup
# from pstr import dotstr

# %% ../nbs/00_core.ipynb 14
def charjoin(char: str, *strs) -> str: return char.join(tuple(argtup(strs)))
def dotstr(*strs) -> str:  return charjoin(DOT, *strs)

# %% ../nbs/00_core.ipynb 16
def pkgstr(*strs) -> str: 
    return dotstr(*argtup(*strs))

def modstr(lib: str, *pkgs: str): 
    return pkgstr(lib, *argtup(*pkgs))

def dostar(v: str) -> bool:
    return (not v.startswith(U1) or v.isupper())

# %% ../nbs/00_core.ipynb 17
def getmods(*mods: str, scope: dict = globals()) -> list[ModuleType]:
    scope = scope or globals()
    return tuple(scope.get(pkgstr(mod)) for mod in mods)

def getall(mod: ModuleType) -> list[str]:
    if hasattr(mod, __ALL__): return getattr(mod, __ALL__)
    if hasattr(mod, __MODULE__): return getall(import_module(getattr(mod, __MODULE__)))
    raise AttributeError(f'''module {mod} has no attribute '__all__' or '__module__'.''')

def getalls(*mods: ModuleType, scope: dict = globals()) -> list[str]:
    scope = scope or globals()
    if mods and isstr(mods[0]): mods = getmods(*mods, scope=scope)
    return sorted(set(chain(*[getall(mod) for mod in mods])))

# %% ../nbs/00_core.ipynb 19
def fromstar(lib: str, *subs: str, scope: dict = globals()):
    '''`from lib.sub.pkg import *`'''
    scope = scope or globals()
    mod = import_module(modstr(lib, *subs))
    scope.update({var: getattr(mod, var) for var in dir(mod) if dostar(var)})

def fromstars(lib: str, *pkgs: str | tuple[str], scope: dict = globals()):
    '''Iterates over `pkgs` calling `fromstar` equivalent to:
    - `from lib.pkg1 import *`
    - `from lib.sub.pkg2 import *`
    '''
    scope = scope or globals()
    for subs in pkgs: fromstar(lib, pkgstr(subs), scope=scope)


def frommod(lib, *subs: str | tuple[str], scope: dict = globals()) -> ModuleType:
    '''`from lib import mod`'''
    scope = scope or globals()
    pkg = pkgstr(subs)
    mod = import_module(modstr(lib, pkg))
    scope.update({pkg: mod})
    return mod

def frommods(lib, *pkgs: str | tuple[str], scope: dict = globals()) -> tuple[ModuleType, ...]:
    '''Iterates over `pkgs` calling `frommod` equivalent to:
    - `from lib import pkg1`
    - `from lib import pkg2`
    '''
    scope = scope or globals()
    return tuple(frommod(lib, *argtup(subs), scope=scope) for subs in pkgs)

# %% ../nbs/00_core.ipynb 23
def expose(lib, *pkgs: str | tuple[str], scope: dict = globals()) -> tuple[ModuleType, ...]:
    scope = scope or globals()
    fromstars(lib, *pkgs, scope=scope)
    modules = frommods(lib, *pkgs, scope=scope)
    __all__ = getalls(*pkgs, scope=scope)
    return modules, __all__
