"""Commands are used to harness the power of nbdev."""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/01_commands.ipynb.

# %% auto 0
__all__ = ['console', 'error_console', 'nbdev_bump_version', 'nbdev_new', 'delegates_sorted', 'bump_version', 'check', 'new']

# %% ../nbs/01_commands.ipynb 2
import types, pathlib, os
from functools import wraps
import typer
from typing_extensions import Annotated
from fastcore.docments import *
from fastcore.meta import delegates
from fastcore.script import call_parse
from fastcore.shutil import rmtree,move
from fastcore.utils import *
from nbdev.quarto import nbdev_readme, refresh_quarto_yml, fs_watchdog
from rich import print
from rich.console import Console
from shutil import which

# %% ../nbs/01_commands.ipynb 3
from nbdev import cli, release, quarto, doclinks, merge, migrate, sync
from nbdev.cli import _update_repo_meta, extract_tgz, _render_nb
from nbdev.config import *
from nbdev.doclinks import nbdev_export
from nbdev import clean as nbclean
from nbdev import test as nbtest

# %% ../nbs/01_commands.ipynb 4
console = Console(style='bold')
error_console = Console(stderr=True, style="bold red")

# %% ../nbs/01_commands.ipynb 6
from fastcore.imports import *
import inspect

# %% ../nbs/01_commands.ipynb 7
def delegates_sorted(to:FunctionType=None, # Delegatee
              keep=False, # Keep `kwargs` in decorated function?
              but:list=None): # Exclude these parameters from signature
    "Decorator: replace `**kwargs` in signature with params from `to`. Sorts arguments."
    if but is None: but = []
    def _f(f):
        if to is None: to_f,from_f = f.__base__.__init__,f.__init__
        else:          to_f,from_f = to.__init__ if isinstance(to,type) else to,f
        from_f = getattr(from_f,'__func__',from_f)
        to_f = getattr(to_f,'__func__',to_f)
        if hasattr(from_f,'__delwrap__'): return f
        sig = inspect.signature(from_f)
        sigd = dict(sig.parameters)
        k = sigd.pop('kwargs')
        s2 = {k:v.replace(kind=inspect.Parameter.KEYWORD_ONLY) for k,v in inspect.signature(to_f).parameters.items()
              if v.default != inspect.Parameter.empty and k not in sigd and k not in but}
        s2 = dict(sorted(s2.items()))
        anno = {k:v for k,v in getattr(to_f, "__annotations__", {}).items() if k not in sigd and k not in but}
        sigd.update(s2)
        if keep: sigd['kwargs'] = k
        else: from_f.__delwrap__ = to_f
        from_f.__signature__ = sig.replace(parameters=sigd.values())
        if hasattr(from_f, '__annotations__'): from_f.__annotations__.update(anno)
        return f
    return _f

# %% ../nbs/01_commands.ipynb 9
nbdev_bump_version = release.nbdev_bump_version.__wrapped__ # remove callparse

@delegates(release.nbdev_bump_version)
def bump_version(**kwargs):
    """
    Bump the version of a project in `settings.ini` and `__version__` within `__init__.py`.
    
    Usage:    
    
    * `nbz bump-version` will increment a 0.0.1 to 0.0.2
    
    * `nbz bump-version --part 1` will increment a 0.0.1 to 0.1.0    
    
    * `nbz bump-version --part 0` will increment a 0.0.1 to 1.0.0
    
    * `nbz bump-version --unbump` will restore the previous version until it has been saved by git.
    
    ---
    
    Learn more [nbz.answer.ai/commands#version-bump](https://nbz.answer.ai/commands#version-bump)
    """        
    return nbdev_bump_version(**kwargs)
bump_version.rich_help_panel = 'nbdev.release'
bump_version.no_args_is_help=False

# %% ../nbs/01_commands.ipynb 10
def check():
    """
    Check that all the components are configured.
    
    Usage:    
    
    * `nbz check`
    
    ---
    
    Learn more [nbz.answer.ai/commands#check](https://nbz.answer.ai/commands#check)
    """
    errors=[]
    
    if which('quarto') is None:
        errors.append('[red]Quarto not yet installed.[/red]\n    Fix: [b]nbz install-quarto[/b]')
        
    if not os.getenv('GITHUB_TOKEN') and not os.getenv('GITHUB_JWT_TOKEN'): 
        errors.append('[red]No github token.[/red]\n    Fix: [b]Set environment variable for GITHUB_TOKEN or GITHUB_JWT_TOKEN[/b]')
        
    try: 
        from twine import settings
        import keyring      
#         cfg = settings.get_repository_config('pypi')
#         console.print(cfg)
#         creds = settings.get_credentials('pypi')
#         if bool(creds.username and creds.password) is False:
#             errors.append('[red]pypi access not setup.[/red]\n    Fix: [b]See https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#create-an-account[/b]')
    except ImportError:
        errors.append('[red]twine not installed.[/red]\n    Fix: [b]pip install twine[/b]')
    
    if errors:
        error_console.print('ERROR: nbdev not fully configured yet.')
        for i, error in enumerate(errors): console.print(f'{i+1}. {error}')
        raise typer.Exit(code=1)
    console.print('[b]Check passed![/b]')
check.rich_help_panel = 'Getting started'
check.no_args_is_help=False

# %% ../nbs/01_commands.ipynb 11
nbdev_new = cli.nbdev_new.__wrapped__ # remove callparse

@delegates_sorted(nbdev_new)
def new(
    target: Annotated[pathlib.Path, typer.Argument(help="Path to create project")],
    **kwargs):
    """
    Create an nbdev project. If the target directory does not exist, creates it.
    
    Usage:
    
    * In your current directory: `nbz new .`
    
    * In a different directory: `nbz new my-project`
    
    ---
    
    Learn more [nbz.answer.ai/commands#new](https://nbz.answer.ai/commands#new)
    """
    # Target directory
    if not target.exists(): 
        console.print(f'Creating and changing to {target} directory')
        target.mkdir()
        os.chdir(target)
    olddir = pathlib.Path('.')
    
    "Create an nbdev project."
    from ghapi.core import GhApi
    nbdev_create_config.__wrapped__(**kwargs)
    with console.status('',spinner="dots"):
        cfg = get_config()
        _update_repo_meta(cfg)
        path = Path()

        _ORG_OR_USR,_REPOSITORY = 'fastai','nbdev-template'
        _TEMPLATE = f'{_ORG_OR_USR}/{_REPOSITORY}'
        template = kwargs.get('template', _TEMPLATE)
        try: org_or_usr, repo = template.split('/')
        except ValueError: org_or_usr, repo = _ORG_OR_USR, _REPOSITORY

        tag = kwargs.get('tag', None)
        if tag is None:
            with warnings.catch_warnings():
                warnings.simplefilter('ignore', UserWarning)
                tag = GhApi(gh_host='https://api.github.com', authenticate=False).repos.get_latest_release(org_or_usr, repo).tag_name

        url = f"https://github.com/{org_or_usr}/{repo}/archive/{tag}.tar.gz"
        extract_tgz(url)
        tmpl_path = path/f'{repo}-{tag}'

        cfg.nbs_path.mkdir(exist_ok=True)
        nbexists = bool(first(cfg.nbs_path.glob('*.ipynb')))
        _nbs_path_sufs = ('.ipynb','.css')
        for o in tmpl_path.ls():
            p = cfg.nbs_path if o.suffix in _nbs_path_sufs else path
            if o.name == '_quarto.yml': continue
            if o.name == 'index.ipynb': _render_nb(o, cfg)
            if o.name == '00_core.ipynb' and not nbexists: move(o, p)
            elif not (path/o.name).exists(): move(o, p)
        rmtree(tmpl_path)

        refresh_quarto_yml()
        nbdev_export.__wrapped__()
        nbdev_readme.__wrapped__()

        # return back to the original directory
        os.chdir(olddir)
new.rich_help_panel = 'Getting started'
new.no_args_is_help=False

