o
    i                    @   s  d dl Z d dlZd dlZd dlZd dlZd dlmZmZmZm	Z	m
Z
 d dlmZ d dlmZ d dlmZ d dlmZmZ d dlmZ d dlmZ d d	lmZ d d
lmZmZmZmZmZmZm Z m!Z!m"Z" d dl#m$Z$m%Z%m&Z& d dl'm(Z( d dl)m*Z* d dl+m,Z, d dl-m.Z.m/Z/m0Z0 d dl1m2Z2 d dl3m4Z4 d dl5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z; d dl<m=Z=m>Z> d dl?m@Z@ d dlAmBZB d dlCmDZDmEZE d dlFmGZG d dlHmIZI d dlJmKZKmLZLmMZMmNZNmOZOmPZPmQZQmRZR ejSdk rn	 eeT d dlUZUW d   n1 sw   Y  erd dlVmWZW d dlXmYZY d dlZm[Z[ d dl\m]Z] d dl^m_Z_m`Z` d d lambZb ed!ed"ef d#Zced$Zdd%Zed&deB ee B d'efed"f dB fd(d)ZgG d*d+ d+ehZid,d- Zjd.d/ Zkd0d1 ZldPd5d6Zmd7eneoef d4d3d'dfd8d9Zpd:eod'eofd;d<Zq	=dQd2ed3 d'eneod>f fd?d@ZrdRdAdBZsdCdeoB e=B d'e=dB fdDdEZte%G dFd3 d3Zud'evdB fdGdHZwG dIdJ dJeoeZxed'exfdKdLZyedMexd'dfdNdOZzdS )S    N)Callable	CoroutineIterableIteratorSequence)suppress)copy)Enum)	lru_cachepartial)chain)Path)
ModuleType)	TYPE_CHECKING	AnnotatedAnyLiteralOptionalTypeVarUnioncastoverload)Factorydefinefield)resolve_annotated)AppStack)ArgumentCollection)create_bound_argumentsis_option_likenormalize_tokens)CommandSpec)Env)CommandCollisionErrorCycloptsErrorUnknownCommandErrorUnknownOptionErrorUnusedCliTokensErrorValidationError)Groupsort_groups)groups_from_app)CycloptsPanel)	Parametervalidate_command)
Dispatcher)Token)UNSET!create_error_console_from_consoledefault_name_transformhelp_formatter_converteroptional_to_tuple_convertersort_key_converterto_list_converterto_tuple_converter)      Console)	DocFormat)	HelpPanel)HelpFormatter)ResultActionResultActionSingle)_run_maybe_async_commandT.)boundVmarkdownvaluereturnc                 C   s$   | du rdS t | }|std|S )zConvert result_action value, ensuring non-empty sequences.

    Intended to be used in an ``attrs.Field`` for result_action.
    Raises ValueError if an empty iterable is provided.
    Nz)result_action cannot be an empty sequence)r8   
ValueError)rG   result rK   S/var/www/html/karishye-ai-python/venv/lib/python3.10/site-packages/cyclopts/core.py_result_action_converterU   s   rM   c                   @   s   e Zd ZdS )#_CannotDeriveCallingModuleNameErrorN)__name__
__module____qualname__rK   rK   rK   rL   rN   f   s    rN   c                  C   sH   t  D ]} t | j}|du rq|jdd }|dkrq|  S t)z1Get the calling package name from the call-stack.N.r   cyclopts)inspectstack	getmoduleframerO   splitrN   )elemmoduleroot_module_namerK   rK   rL   _get_root_module_namej   s   r\   c                 C   s   t | tr	td| S )N%Cannot register a sub-App to default.)
isinstanceApp	TypeErrorxrK   rK   rL   _validate_default_commandx   s   
rc   c                 C   s"   t | jrt| jr| jS | jS N)callableversionrT   iscoroutinefunction_version_print_asyncversion_print)apprK   rK   rL   _get_version_command~   s   rk   rj   r_   
parent_appc                 C   sj   | j du rt|j | _ | jdu rt|j| _| jdu r!t|j| _| jdu r1|jdur3|j| _dS dS dS )zApply parent app's group defaults to app if not already set.

    Parameters
    ----------
    app : App
        The app to apply defaults to.
    parent_app : App
        The parent app to inherit defaults from.
    N)_group_commandsr   _group_parameters_group_argumentsrf   )rj   rl   rK   rK   rL   _apply_parent_defaults_to_app   s   



rp   kwargsc                 C   sJ   d| vrt |j| d< d| vrt |j| d< d| vr#t |j| d< dS dS )zApply parent app's groups to kwargs dict if not already specified.

    Parameters
    ----------
    kwargs : dict
        Keyword arguments dict to modify.
    parent_app : App
        The parent app to inherit groups from.
    group_commandsgroup_parametersgroup_argumentsN)r   rm   rn   ro   )rq   rl   rK   rK   rL   _apply_parent_groups_to_kwargs   s   
ru   sc                 C   s   |  dd dd S )am  Normalize a string for fuzzy command matching.

    Removes hyphens, underscores, and converts to lowercase (e.g.,
    'mycommand' matches 'my-command').

    .. warning::
        This fuzzy matching is primarily for backward compatibility with the
        introduction of ``_pascal_to_snake`` in ``default_name_transform``.
        It should **probably be removed in v5** once users have migrated their
        camelCase command names.

    Parameters
    ----------
    s : str
        String to normalize.

    Returns
    -------
    str
        Normalized string with hyphens/underscores removed and lowercased.
    - _)replacelower)rv   rK   rK   rL   _normalize_for_matching   s   r|   TApp | CommandSpecc                 C   s   | du ri S t | j}| jD ]}|D ]}||vr|| ||< qq|r/| jr/|t| jdd |r@| jr@t| jdd}|| |S )af  Return a mapping of command names to Apps or CommandSpecs.

    CommandSpec instances are NOT resolved here - they are resolved lazily
    only when the command is actually executed, enabling true lazy loading.

    Parameters
    ----------
    app : App | None
        The app to get commands from.
    recurse_meta : bool
        If True, include commands from the app's meta.
    recurse_parent_meta : bool
        If True, include commands from parent meta apps.

    Returns
    -------
    dict[str, App | CommandSpec]
        Mapping of command names to :class:`App` or :class:`CommandSpec` instances.
    NFrecurse_parent_metarecurse_meta)dict	_commands_flattened_subapps_metaupdate_combined_meta_command_mapping_meta_parent)rj   r   r   command_mappingsubappcmd_namemeta_parent_commandsrK   rK   rL   r      s   




r   c                 c   sH    | g}| }|j  }r|jr|| |j  }r|jst|E dH  dS )z{Typically the result looks like [app] or [meta_app, app].

    Iterates from deepest to shallowest meta-app (and app).
    N)r   default_commandappendreversed)rj   	meta_listmetarK   rK   rL   _walk_metas   s   
r   input_valuec                 C   s0   | d u rd S t | trt| S t | tr| S trd   )r^   strr)   r`   )r   rK   rK   rL   _group_converter   s   

r   c                   @   s  e Zd ZU eddedZdeB eedf B ed< edddZ	edB ed< edd	Z
edB ed
< ededdZdeB eedf B ed< ededdZedef dB ed< edddZedB ed< eddeddZdeed  eedf egef B eeed  eedf egef  B ed< edddZdeB edef B edeeeef f B ed< edgedddZeee B ed< edddZeed< eddddZed ed< eddddZed ed< ed d!ged"ddZeee B ed#< edddZ e!d$ dB ed%< edddZ"edB ed&< edddZ#edB ed'< edddZ$e!d$ dB ed(< ededdZ%e&eB ee&eB df B ed)< ed*de'dd+Z(e&eB dB ed,< ed-de'dd+Z)e&eB dB ed.< ed/de'dd+Z*e&eB dB ed0< ede+ddZ,eedef  ed1< edd2dd3Z-eegef dB ed4< edd5e.ddZ/eed6< edddZ0edB ed7< edddZ1edB ed8< edddZ2edB ed9< edddZ3edB ed:< edddZ4eed;< edddZ5e!d< dB ed=< ede6ddZ7e8de!d> d?f ed@< ede9ddZ:e;e<B dB edA< edBe=dCZ>e=edDf edE< edBedCZ?ed  edF< edBddGZ@ed  edH< edBddGZAed  edI< edBddBdJZBedB edK< 	 edBeCdBdJZDeEdB eFeC B edL< 	 edBddGZGed edM< edBddGZHed edN< edBeIeJddOdGZKeJedP< dQdR ZLdSee fdTdUZMeNdVdW ZOeOjPdXdW ZOeNdYdZ ZQeQjPd[dZ ZQeNd\eedf fd]d^ZReNd_d` ZSeSjPdad` ZSeNdbdc ZTeTjPdddc ZTeNdedf ZUeUjPdgdf ZUeNdhdi ZVeVjPdjdi ZVeNd\efdkdlZWeWjPdmdl ZWeNdndo ZXeXjPdpdo ZXeNdqdr ZYeYjPdsdr ZYeNd\e=ed f fdtduZZeNddvdwZ[e[jPded fdxdwZ[eNddydzZ\e\jPded fd{dzZ\eNd\eEdB fd|d}Z]dded\efddZ^deded d\dfddZ_	dde`ed edBdf d\dfddZa	dde`ed edBdf d\dfddZbeNdd Zcd\e=ed f fddZdded\d fddZeddddZfdefddZgded\efddZhd\eie fddZjeNdddZk	dddddeB ee B d\eeedf ed ee f fddZldemd  d\ed  fddZnded  dee d\ee fddZoep	ddddeqddeB ee B ddeB ee B derd\eqf
ddZsep		d ddddddeB ee B ddeB ee B derd\eeqgeqf f
ddZsep	ddddeddeB ee B ddeB ee B derd\df
ddZs		d dddeqdB eB ddeB ee B ddeB ee B derd\eqeeqgeqf B dB f
ddZsepdddeqd1edef dB d\eqfddZtep	dddddd1edef dB d\eeqgeqf fddZt	ddddeqdB d1edef dB d\eqeeqgeqf B fddZtddBddedB ded\efddZu	dddddddeB ee B ded ded d7edB d\eedef evjwee e=eef f f
ddZx	ddBdddeB ee B ded\eedef evjwee e=eef ef fddZy	dddddddddddeB ee B ded ded d8edB d9edB d&edB d:edB d7edB d\eeevjwe=eef f fddZzd\efddÄZ{	dddddddddddĜ	ddeB ee B ded ded d8edB d9edB d&edB d:edB d7edB d=e!d< dB dAe;dB d\efddƄZ|	dddddddddddĜ	ddeB ee B ded ded d8edB d9edB d&edB d:edB d7edB d=e!d< dB dAe;dB d\efddȄZ}	dddɜde`deB ee B edBdʍf de`ed edBdf d\dfdd̄Z~ddeB ee B d\eeed df  fddЄZ			B		Bddddedededed\efddڄZdddۜdedB de!d dB d\efddZddddde!d dB dedB ded\efddZ		ddeee B ded\dfddZ					B	ddeddeB ee B dedB ddd9edAe;dB d\dfddZddede;d\efddZdddZdd ZdS (  r_   Nname)defaultalias	converter._namehelp)r   r   _help)r   usageT)r   r   kw_onlyr   r   )r   r   default_parameterconfig)r   r   r   r   _configrf   z	--versionversion_flags)r   r   r   r   _version_flagsshowconsole)r   r   r   r<   _consoleerror_console_error_consolez--helpz-h
help_flags_help_flags)rF   md	plaintextrestructuredtextrstrichhelp_formathelp_on_errorhelp_epilogueversion_formatgrouprt   )r   r   r   r   ro   rs   rn   rr   rm   	validatorname_transform)r   r   r   _name_transformsort_key	_sort_keyend_of_options_delimiterprint_errorexit_on_errorverbosesuppress_keyboard_interruptasynciotriobackend)r   plainr?   help_formatterresult_actionF)initfactoryr}   r   r   )r   r   r   r   )r   r   repr_instantiating_module_name_instantiating_module_cache_fallback_console_fallback_error_console)
takes_self	app_stackc              	   C   sN   | j | _| j| _ztd}|jd| _W d S  t	t
fy&   d | _Y d S w )N   rO   )r   r   r   r   sys	_getframe	f_globalsgetr   
IndexErrorAttributeError)selfrW   rK   rK   rL   __attrs_post_init__  s   
zApp.__attrs_post_init__commandsc              	   C   s*   |D ]}z| |= W q t y   Y qw dS )zSafely delete commands.

        Will **not** raise an exception if command(s) do not exist.

        Parameters
        ----------
        commands: Iterable[str, ...]
            Strings of commands to delete.
        N)KeyError)r   r   commandrK   rK   rL   _delete_commands  s   
zApp._delete_commandsc                 C      | j S rd   )r   r   rK   rK   rL   r        zApp.version_flagsc                 C   <   |  | j || _| jr| j| j| jg g | jdd d S d S )NzDisplay application version.r   r   r   rf   r   )r   r   r   ri   rf   r   rG   rK   rK   rL   r        
c                 C   r   rd   )r   r   rK   rK   rL   r     r   zApp.help_flagsc                 C   r   )NzDisplay this message and exit.r   )r   r   r   
help_printrf   r   rK   rK   rL   r     r   rH   c                 C   s   | j r	| j | j S | jdu r#ttjd j}|dkrt }|f| j S z| jj}W n t	y7   | jj
j}Y nw | |f| j S )z?Application name(s). Dynamically derived if not previously set.Nr   z__main__.py)r   r   r   r   r   argvr   r\   rO   r   funcr   )r   r   	func_namerK   rK   rL   r     s   
zApp.namec                 C      | j d u r	t S | j S rd   )ro   r)   create_default_argumentsr   rK   rK   rL   rt        
zApp.group_argumentsc                 C   
   || _ d S rd   )ro   r   rK   rK   rL   rt        
c                 C   r   rd   )rn   r)   create_default_parametersr   rK   rK   rL   rs     r   zApp.group_parametersc                 C   r   rd   )rn   r   rK   rK   rL   rs     r   c                 C   r   rd   )rm   r)   create_default_commandsr   rK   rK   rL   rr     r   zApp.group_commandsc                 C   r   rd   )rm   r   rK   rK   rL   rr   %  r   c                 C   s   | j dS )Nr   )r   resolver   rK   rK   rL   r   )  s   z
App.configc                 C   r   rd   )r   r   rK   rK   rL   r   -  r   c                 C   s   | j d ur| j S | jd u r| jd u rdS | jjS dtjv r4ddlm} t	| j|r/| jj
j}n	| jj}n| jj}|d u r>dS |S )Nrx   	functoolsr   r   )r   r   r   r   r   r   modulesr   r   r^   r   __doc__)r   r   docrK   rK   rL   r   1  s   




zApp.helpc                 C   r   rd   )r   r   rK   rK   rL   r   L  r   c                 C   s   | j r| j S tS rd   )r   r3   r   rK   rK   rL   r   P  s   zApp.name_transformc                 C   r   rd   )r   r   rK   rK   rL   r   T  r   c                 C   s   | j tu rd S | j S rd   )r   r1   r   rK   rK   rL   r   X  s   zApp.sort_keyc                 C   s   t || _d S rd   )r6   r   r   rK   rK   rL   r   \  s   c                 C   s4   i }| D ]}|| j v s|| jv rq| | ||< q|S )zpCommands that are not help or version commands.

        This includes commands from flattened subapps.
        )r   r   )r   outrb   rK   rK   rL   _registered_commands`  s   zApp._registered_commandsc                 C   s<   | j d}|d ur|S | jd u rddlm} | | _| jS )Nr   r   r;   )r   r   r   rich.consoler<   )r   rJ   r<   rK   rK   rL   r   m  s   
zApp.consolec                 C   r   rd   )r   r   r   rK   rK   rL   r   }  r   c                 C   s4   | j d}|d ur|S | jd u rt| j| _| jS )Nr   )r   r   r   r2   r   )r   rJ   rK   rK   rL   r     s   
zApp.error_consolec                 C   r   rd   )r   r   rK   rK   rL   r     r   c                 C   s8   | j tu r| jrtj| j| _ nd| _ ttdB | j S )z2Lazily resolve the module name to a module object.N)r   r1   r   r   r   r   r   r   r   rK   rK   rL   _instantiating_module  s
   
zApp._instantiating_module0.0.0r   c              	   C   s   ddl m} ddl m} | jdur:| jj}|dd }z||W S  |y*   Y nw z| jjW S  ty9   Y nw zt }W n t	yJ   | Y S w z||W S  |yY   Y nw z	t
|}|jW S  ttfyo   Y |S w )a  Get the version string with multiple fallback strategies.

        First tries to derive from the instantiating module, then tries to get it
        from the calling code's module, and finally falls back to a default.

        Parameters
        ----------
        default : str
            Default version to use if no version can be determined.

        Returns
        -------
        str
            Version string.
        r   )PackageNotFoundError)rf   NrR   )importlib.metadatar   rf   r   rO   rX   __version__r   r\   rN   	importlibimport_moduleImportError)r   r   r   importlib_metadata_versionfull_module_namer[   rZ   rK   rK   rL   _get_fallback_version_string  s@   





z App._get_fallback_version_stringversion_rawc                 C   sR   ddl m} | jd}|du r| jjdtd}|j||d}|p#| j| dS )zFormat and print the version string.

        Parameters
        ----------
        version_raw : str
            Raw version string to format and print.
        console : ~rich.console.Console
            Console to print to.
        r   
InlineTextr   Nr   fallbackformat)cyclopts.helpr  r   r   _DEFAULT_FORMATfrom_formatr   print)r   r  r   r  r   version_formattedrK   rK   rL   _format_and_print_version  s   
zApp._format_and_print_versionparsec                 C   sX   | j dur t| j rt| j rtdtt|   }n| j }n|  }| || dS )a   Print the application version.

        Parameters
        ----------
        console: ~rich.console.Console
            Console to print version string to.
            If not provided, follows the resolution order defined in :attr:`App.console`.

        NzJasync version handler detected. Use App.run_async within an async context.)	rf   re   rT   rg   rI   r   r   r  r  r   r   r  rK   rK   rL   ri     s   

zApp.version_printc                    sb   | j dur%t| j r!t| j r|   I dH }ntt|   }n| j }n|  }| || dS )a&  Async version of version_print for handling async version callables.

        Parameters
        ----------
        console: ~rich.console.Console
            Console to print version string to.
            If not provided, follows the resolution order defined in :attr:`App.console`.

        N)rf   re   rT   rg   r   r   r  r  r  rK   rK   rL   rh     s   

zApp._version_print_asyncc                 c   s    | D ]}| | V  qd S rd   rK   )r   krK   rK   rL   subapps  s   zApp.subappsc                    sF    fdd j  D } jD ]}|D ]}||vr|| ||< qq|S )a  Get all commands as resolved App instances.

        This function resolves any lazy-loaded commands (CommandSpec) into App instances.
        Note: This will import modules for all lazy-loaded commands, which may impact performance
        and memory usage. Consider accessing commands individually via ``app["command_name"]`` if
        you don't need all commands at once.

        Returns
        -------
        dict[str, App]
            Mapping of command names to resolved :class:`App` instances.

        Examples
        --------
        .. code-block:: python

            from cyclopts import App

            app = App()
            app.command("myapp.commands:create")
            app.command("myapp.commands:delete")

            # Resolve all lazy commands
            commands = app.resolved_commands()
            assert "create" in commands
            assert isinstance(commands["create"], App)
        c                    s*   i | ]\}}|t |tr| n|qS rK   )r^   r!   r   ).0r   cmdr   rK   rL   
<dictcomp>9  s    z)App.resolved_commands.<locals>.<dictcomp>)r   itemsr   )r   resolvedr   r   rK   r   rL   resolved_commands  s   

zApp.resolved_commandskeyc                 C   s"   |  |}t|tr|| S |S )aN  Get the subapp from a command string.

        All commands get registered to Cyclopts as subapps.
        The actual function handler is at ``app[key].default_command``.

        If the command was registered via lazy loading (import path string),
        it will be imported and resolved on first access.

        Example usage:

        .. code-block:: python

            from cyclopts import App

            app = App()
            app.command(App(name="foo"))


            @app["foo"].command
            def bar():
                print("Running bar.")


            app()
        )	_get_itemr^   r!   r   )r   r  r  rK   rK   rL   __getitem__E  s   


zApp.__getitem__c              	   C   s   |r!| j r!tt | jj|ddW  d   S 1 sw   Y  | jr@tt | jj|ddW  d   S 1 s;w   Y  || jv rJ| j| S | jD ]}tt |j|ddW  d     S 1 sgw   Y  qMt|)z;Internal getter that returns App or unresolved CommandSpec.Tr   NF)r   r   r   r   r  r   r   r   )r   r  r   r   rK   rK   rL   r  e  s   

 
 



&zApp._get_itemc                 C   s   | j |= d S rd   )r   )r   r  rK   rK   rL   __delitem__y  s   zApp.__delitem__r  c                 C   s@   || j v rdS | jr|| jv rdS | jD ]	}||v r dS qdS )NTF)r   r   r   )r   r  r   rK   rK   rL   __contains__|  s   


zApp.__contains__c                 c   sz    t | j}|E dH  t|}| jr$| jD ]}||vr#|V  || q| jD ]}|D ]}||vr9|V  || q+q'dS )a  Iterate over command & meta command names.

        Example usage:

        .. code-block:: python

            from cyclopts import App

            app = App()


            @app.command
            def foo():
                pass


            @app.command
            def bar():
                pass


            # help and version flags are treated as commands.
            assert list(app) == ["--help", "-h", "--version", "foo", "bar"]
        N)listr   setr   addr   )r   r   r   r   rK   rK   rL   __iter__  s$   





zApp.__iter__c                 C   sJ   | j d u r"t| | j| jt| jt| jt| j| jd| _ | | j _	| j S )N)r   r   rr   rt   rs   r   )
r   typer   r   r   rm   ro   rn   r   r   r   rK   rK   rL   r     s   
zApp.metainclude_parent_metatokens)r_   .c                   sb  t |}g }| }g  |} fdd}||  | t|d}|}|r|d }d}	||v r5|| }	n0t|fdd|D }
t|
dkrO||
d  }	nt|
dkretd	| d
dt|
 d|	du r}r||  |}t|t|k r||}q$n+t	|	t
r|}|	|}n|	}||  | t|d}|| |dd }|s&t|t |fS )a  Extract out the command tokens from a command.

        You are probably actually looking for :meth:`parse_args`.

        Parameters
        ----------
        tokens: None | str | Iterable[str]
            Either a string, or a list of strings to launch a command.
            Defaults to ``sys.argv[1:]``
        include_parent_meta: bool
            Controls whether parent meta apps are included in the execution path.

            When True (default):
            - Parent meta apps (i.e. the "normal" app ) are added to the apps list.
            - Meta app options are consumed while parsing commands.
            - Used for getting the inheritance hierarchy.

            When False:
            - Meta app options are treated as regular arguments.
            - Used for getting the execution hierarchy.

            This parameter is primarily for internal use.

        Returns
        -------
        tuple[str, ...]
            Strings that are interpreted as a valid command chain.
        tuple[App, ...]
            The execution path - apps that will be invoked in order.
        list[str]
            The remaining non-command tokens.
        c                    sN   sdS g }| }|j  }dur|| |j  }dus |ddd  dS )zIf ``app`` is a meta-app, also add it's "normal" app.

            We assume that ``app._meta`` will always invoke the ``app``.
            N)r   r   extend)rj   meta_parentsmeta_parent)appsr&  rK   rL   add_parent_metas  s   
z,App.parse_commands.<locals>.add_parent_metasr~   r   Nc                    s   g | ]
}t | kr|qS rK   )r|   )r  r   )normalized_tokenrK   rL   
<listcomp>
  s    z&App.parse_commands.<locals>.<listcomp>   zAmbiguous command 'z'. Could match: , rR   )r    r   r   r|   lenrI   joinsorted_consume_leading_meta_optionsr^   r!   r   tuple)r   r'  r&  command_chainrj   unused_tokensr-  r   tokenapp_or_specmatches	remainingrl   rK   )r,  r&  r.  rL   parse_commands  sR   &


 


4zApp.parse_commandsexecution_pathc                 C   s~   g }|r=|d }t |D ]}||vr|| q|jjr=|jjd D ]}|jr<|j|vr<||jj v }|s<||j q"|S )a  Get all apps that contribute to parameter resolution for the given execution path.

        This includes parent meta apps and the meta app of the final command app.

        Parameters
        ----------
        execution_path : Sequence[App]
            The execution path returned from parse_commands.

        Returns
        -------
        list[App]
            All apps that contribute configuration and parameters, ordered by priority.
        r(  )r   r   r   rU   r   r   values)r   r>  r,  last_apprj   is_meta_commandrK   rK   rL   _get_resolution_context4  s   
zApp._get_resolution_contextr,  c           	   	   C   s   |r|s|S ddl m} | | | jjddd}W d   n1 s$w   Y  dd |D }|d	 jrC|d	 jjrC||d	 j |}|D ]}z| }||||d
d}W qG ty`   Y qGw |S )a  Consume meta app options from the beginning of the token stream.

        This is used to skip over meta app parameters when looking for commands.

        Limitation: positional parameters for the meta app are NOT skipped.
        This is because we do not know which meta-parameters are for the
        meta-app itself vs which it will pass along to the normal app.

        Parameters
        ----------
        apps: list[App]
            Current app stack including parent meta apps.
        tokens: list[str]
            Tokens to try parsing, starting from current position.

        Returns
        -------
        list[str]
            The remaining unused tokens after consuming any leading meta options.
        r   )_parse_kw_and_flagsr   --r  Nc                 S   s    g | ]}|j d ur|jr|qS rd   )r   r   )r  rj   rK   rK   rL   r/  {  s     z5App._consume_leading_meta_options.<locals>.<listcomp>r(  T)r   stop_at_first_unknown)	cyclopts.bindrC  r   r   r   r   r   assemble_argument_collection	Exception)	r   r,  r'  rC  r   meta_apps_to_tryr8  meta_appargument_collectionrK   rK   rL   r5  Y  s.   
z!App._consume_leading_meta_options)r   objrq   c                K      d S rd   rK   r   rL  r   r   rq   rK   rK   rL   r        zApp.commandc                K   rM  rd   rK   rN  rK   rK   rL   r     rO  c                K   rM  rd   rK   rN  rK   rK   rL   r     rO  c                K   s0  |du rt | jf||d|S |dkr0t|tstd|r#tdt||  | j| |S t|t	r~|du rH|
d\}}}| |f}nt|}|du rSd}nt|}t||r_|d nd|d	}|| D ]}|| v rvtd
| d|| j|< qhdS t|tr|}	|	jdu r|du rtd|rtdt|	|  n/|d| j |d| j d|vr| jdur| j|d< t||  t| di |}	|	| t|	j|	jD ]}
d|	|
 _q|	jdu r| j|	_|du r|	j}nt|}|du rd}nt|}|| D ]}|| v rtd
| d|	| j|< q |S )aE  Decorator to register a function as a CLI command.

        Example usage:

        .. code-block::

            from cyclopts import App

            app = App()

            @app.command
            def foo():
                print("foo!")

            @app.command(name="buzz")
            def bar():
                print("bar!")

            # Lazy loading via import path
            app.command("myapp.commands:create_user", name="create")

            app()

        .. code-block:: console

            $ my-script foo
            foo!

            $ my-script buzz
            bar!

            $ my-script create
            # Imports and runs myapp.commands:create_user

        Parameters
        ----------
        obj: Callable | App | str | None
            Function, :class:`App`, or import path string to be registered as a command.
            For lazy loading, provide a string in format "module.path:function_or_app_name".
        name: None | str | Iterable[str]
            Name(s) to register the command to.
            If not provided, defaults to:

            * If registering an :class:`App`, then the app's name.
            * If registering a **function**, then the function's name after applying :attr:`name_transform`.
            * If registering via **import path**, then the attribute name after applying :attr:`name_transform`.

            Special value ``"*"`` flattens all sub-App commands into this app (App instances only).
            See :ref:`Flattening SubCommands` for details.
        `**kwargs`
            Any argument that :class:`App` can take.
        N)r   r   *zYFlattening (name="*") is only supported for App instances, not functions or import paths.zLCannot supply additional configuration when flattening a sub-App (name="*").:rK   r   )import_pathr   
app_kwargsz	Command "z" already registered.z#Sub-app MUST have a name specified.zDCannot supplied additional configuration when registering a sub-App.r   r   rf   F)r   r   r^   r_   r`   rI   rp   r   r   r   
rpartitionr   r8   r!   r#   r   r   
setdefaultr   r   rf   ru   r$  r   r   r   r   r   )r   rL  r   r   rq   ry   r   specnrj   flagrK   rK   rL   r     sn   <








r   c                C   rM  rd   rK   r   rL  r   rK   rK   rL   r   X     zApp.defaultc                C   rM  rd   rK   rZ  rK   rK   rL   r   e  r[  c                C   s`   |du rt | j|dS t|trtd| jdur"td| j dt| || _|r.|| _|S )a  Decorator to register a function as the default action handler.

        Example usage:

        .. code-block:: python

            from cyclopts import App

            app = App()


            @app.default
            def main():
                print("Hello world!")


            app()

        .. code-block:: console

            $ my-script
            Hello world!
        NrY  r]   z"Default command previously set to rR   )	r   r   r^   r_   r`   r   r#   r.   r   rZ  rK   rK   rL   r   m  s   

)r   parse_docstringr\  c                C   s8   | j du r	tdtj| j t| jj|| j| j	|dS )a  Assemble the argument collection for this app.

        Parameters
        ----------
        default_parameter: Parameter | None
            Default parameter with highest priority.
        parse_docstring: bool
            Parse the docstring of :attr:`default_command`.
            Set to :obj:`True` if we need help strings, otherwise set to :obj:`False` for performance reasons.

        Returns
        -------
        ArgumentCollection
            All arguments for this app.
        NzCannot assemble argument collection: no default command is registered. Use @app.default to register a default command, or access a specific subcommand's argument collection via app['command_name'].assemble_argument_collection().)rt   rs   r\  )
r   rI   r   _from_callabler-   combiner   r   ro   rn   )r   r   r\  rK   rK   rL   rG    s   
z App.assemble_argument_collection)r   r   r   c                C   sZ   |||d}| j g |d | |\}}}}	}
W d   n1 s"w   Y  ||||	fS )a&  Interpret arguments into a registered function, :class:`~inspect.BoundArguments`, and any remaining unknown tokens.

        Parameters
        ----------
        tokens: None | str | Iterable[str]
            Either a string, or a list of strings to launch a command.
            Defaults to ``sys.argv[1:]``
        console: ~rich.console.Console
            Console to print help and runtime Cyclopts errors.
            If not provided, follows the resolution order defined in :attr:`App.console`.
        error_console: ~rich.console.Console
            Console to print error messages.
            If not provided, follows the resolution order defined in :attr:`App.error_console`.
        end_of_options_delimiter: str | None
            All tokens after this delimiter will be force-interpreted as positional arguments.
            If None, inherits from :attr:`App.end_of_options_delimiter`, eventually defaulting to POSIX-standard ``"--"``.
            Set to an empty string to disable.

        Returns
        -------
        command: Callable
            Bare function to execute.

        bound: inspect.BoundArguments
            Bound arguments for ``command``.

        unused_tokens: list[str]
            Any remaining CLI tokens that didn't get parsed for ``command``.

        ignored: dict[str, Any]
            A mapping of python-variable-name to annotated type of any
            parameter with annotation ``parse=False``.
            :obj:`~typing.Annotated` will be resolved.
            Intended to simplify :ref:`meta apps <Meta App>`.
        )r   r   r   	overridesN)r   _parse_known_args)r   r'  r   r   r   r`  r   rD   r8  ignoredry   rK   rK   rL   parse_known_args  s   ,zApp.parse_known_argsraise_on_unused_tokensre  c                   sP  d u r	t t  t| }| jdd\}}}| jdd\}}|d  tt8 r\d t|d j|d j v r\|d d }d d r\d t|d j|d j v s>W d    n1 sfw   Y  |d  ~i }| 	|  j	
dpd}	t fdd	|	D }	| j	j
d
dd}
t j|
}zN|d urt j j fddD d d < fdd|D |d d < | j}|j }r|j}|j }st|j jd}g }t }ntfdd	 jD rt }|j }rt|}|j }st|j jd}g }t }n jr j}t|   }dd |jddD }t j|||	|
d\}}z jD ]}|di |j q?W n  tttfyl } zt |j!rb|j!d nd d|d }~ww z j	j"D ]}|jD ]}|di |j qwqrW n; tttfy } zt |j!r|j!d nd|d|d }~ww |rt#|d| j}t|j jd}g }t }|r|r|D ]}t$|r|%dd }t&t'|dd|dqt(||d W n% t)y } z j|_* |_+r|_,|jd u r j-|_ d }~ww W d    n	1 sw   Y  |||||fS )!NTr%  Fr(  r   rK   c                 3   s    | ]	}t | V  qd S rd   r   r  rb   )command_appr7  rK   rL   	<genexpr>  s    z(App._parse_known_args.<locals>.<genexpr>r   rD  r  c                       g | ]}| vr|qS rK   rK   r  tflags_to_removerK   rL   r/  *      z)App._parse_known_args.<locals>.<listcomp>c                    rj  rK   rK   rk  rm  rK   rL   r/  +  ro  r   c                 3   s    | ]}| v V  qd S rd   rK   )r  rX  )r'  rK   rL   ri  3  s    c                 S   s   i | ]}|j jt|j jqS rK   )
field_infor   r   
annotation)r  argumentrK   rK   rL   r  @  s    z)App._parse_known_args.<locals>.<dictcomp>r  )r   r   rx   )exception_messagerj   )rt  r   )r8  )r'  r   =cli)keywordsource)r9  rK  )targetr8  )._log_framework_warning_detect_test_frameworkr    r=  r   r   r!  r   r   r   r   r6  _get_help_flag_indexr   r   rT   	signaturebindr   r   anyrk   r   r.   rG  	filter_byr   r   	argumentsAssertionErrorrI   r`   r(   argscommand_groupsr%   r   rX   r&   r0   r'   r$   ry  rj   r7  r   )r   r'  re  r+  ry   apps_for_contextexecution_appsr8  rb  r   r   help_flag_indexr   rD   rK  r   ecommand_groupr9  rK   )rh  r7  rn  r'  rL   ra    s   







 



_zApp._parse_known_args)r   r   r   r   r   r   r   c                C   s\  |du r	t t  t|}dd |||||||d D }	| jg |	d| z| j|dd\}
}}}}W ne ty } zY| jd}| jd	}| jd
}| jd}|durZ|nd|_||_	|j
dusgJ |durn|rwnn| j||j
d |dur~|rn	 |j
t| |dur|rn	 td  d}~ww W d   n1 sw   Y  |
||fS )a	  Interpret arguments into a function and :class:`~inspect.BoundArguments`.

        Raises
        ------
        UnusedCliTokensError
            If any tokens remain after parsing.

        Parameters
        ----------
        tokens: None | str | Iterable[str]
            Either a string, or a list of strings to launch a command.
            Defaults to ``sys.argv[1:]``.
        console: ~rich.console.Console
            Console to print help and runtime Cyclopts errors.
            If not provided, follows the resolution order defined in :attr:`App.console`.
        error_console: ~rich.console.Console
            Console to print error messages.
            If not provided, follows the resolution order defined in :attr:`App.error_console`.
        print_error: bool | None
            Print a rich-formatted error on error.
            If :obj:`None`, inherits from :attr:`App.print_error`, eventually defaulting to :obj:`True`.
        exit_on_error: bool | None
            If there is an error parsing the CLI tokens invoke ``sys.exit(1)``.
            Otherwise, continue to raise the exception.
            If :obj:`None`, inherits from :attr:`App.exit_on_error`, eventually defaulting to :obj:`True`.
        help_on_error: bool | None
            Prints the help-page before printing an error.
            If :obj:`None`, inherits from :attr:`App.help_on_error`, eventually defaulting to :obj:`False`.
        verbose: bool | None
            Populate exception strings with more information intended for developers.
            If :obj:`None`, inherits from :attr:`App.verbose`, eventually defaulting to :obj:`False`.
        end_of_options_delimiter: str | None
            All tokens after this delimiter will be force-interpreted as positional arguments.
            If :obj:`None`, inherits from :attr:`App.end_of_options_delimiter`, eventually defaulting to POSIX-standard ``"--"``.
            Set to an empty string to disable.

        Returns
        -------
        command: Callable
            Function associated with command action.

        bound: inspect.BoundArguments
            Parsed and converted ``args`` and ``kwargs`` to be used when calling ``command``.

        ignored: dict[str, Any]
            A mapping of python-variable-name to type-hint of any parameter with annotation ``parse=False``.
            :obj:`~typing.Annotated` will be resolved.
            Intended to simplify :ref:`meta apps <Meta App>`.
        Nc                 S      i | ]\}}|d ur||qS rd   rK   r  r  vrK   rK   rL   r    s
    	
z"App.parse_args.<locals>.<dictcomp>)r   r   r   r   r   r   r   r_  Trd  r   r   r   r   Frp  r0  )rz  r{  r    r  r   ra  r$   r   r   root_input_tokensr   r   r  r,   r   exit)r   r'  r   r   r   r   r   r   r   r`  r   rD   ry   rb  r  rK   rK   rL   
parse_argsz  sP   =


zApp.parse_argsc                 C   s,   t | jjdkp| jduot | jjjdkS )zHCheck if this is a nested call (meta app pattern or same-app recursion).r0  N)r2  r   overrides_stackr   r   rK   rK   rL   _is_nested_call  s   zApp._is_nested_call)	r   r   r   r   r   r   r   r   r   c       	      
   C   s  |du r	t t  t|}dd |||||||	|
d D }|  r)|dd | ||H | j|||d\}}}tt	d | jj
d	d
d}zt|||}| |W W  d   S  tyn   | jrktd n Y nw W d   dS 1 szw   Y  dS )ax
  Interprets and executes a command.

        Parameters
        ----------
        tokens : None | str | Iterable[str]
            Either a string, or a list of strings to launch a command.
            Defaults to ``sys.argv[1:]``.
        console: ~rich.console.Console
            Console to print help and runtime Cyclopts errors.
            If not provided, follows the resolution order defined in :attr:`App.console`.
        error_console: ~rich.console.Console
            Console to print error messages.
            If not provided, follows the resolution order defined in :attr:`App.error_console`.
        print_error: bool | None
            Print a rich-formatted error on error.
            If :obj:`None`, inherits from :attr:`App.print_error`, eventually defaulting to :obj:`True`.
        exit_on_error: bool | None
            If there is an error parsing the CLI tokens invoke ``sys.exit(1)``.
            Otherwise, continue to raise the exception.
            If :obj:`None`, inherits from :attr:`App.exit_on_error`, eventually defaulting to :obj:`True`.
        help_on_error: bool | None
            Prints the help-page before printing an error.
            If :obj:`None`, inherits from :attr:`App.help_on_error`, eventually defaulting to :obj:`False`.
        verbose: bool | None
            Populate exception strings with more information intended for developers.
            If :obj:`None`, inherits from :attr:`App.verbose`, eventually defaulting to :obj:`False`.
        end_of_options_delimiter: str | None
            All tokens after this delimiter will be force-interpreted as positional arguments.
            If :obj:`None`, inherits from :attr:`App.end_of_options_delimiter`, eventually defaulting to POSIX-standard ``"--"``.
            Set to an empty string to disable.
        backend: Literal["asyncio", "trio"] | None
            Override the async backend to use (if an async command is invoked).
            If :obj:`None`, inherits from :attr:`App.backend`, eventually defaulting to "asyncio".
            If passing backend="trio", ensure trio is installed via the extra: `cyclopts[trio]`.
        result_action: ResultAction | None
            Controls how command return values are handled. Can be a predefined literal string
            or a custom callable that takes the result and returns a processed value.
            If :obj:`None`, inherits from :attr:`App.result_action`, eventually defaulting to "print_non_int_return_int_as_exit_code".
            See :attr:`App.result_action` for available modes.

        Returns
        -------
        return_value: Any
            The value the command function returns.
        Nc                 S   r  rd   rK   r  rK   rK   rL   r  +  
    
z App.__call__.<locals>.<dictcomp>r   r   r   r   r   r   r   r   r   return_valuer   r   r   r   r   r     )rz  r{  r    r  r  rU  r   r  r   r   r   rB   _handle_result_actionKeyboardInterruptr   r   r  )r   r'  r   r   r   r   r   r   r   r   r   r`  r   rD   ry   resolved_backendrJ   rK   rK   rL   __call__  sH   ;
	
"zApp.__call__c       	      
      s  |du r
t t  t|}dd |||||||	|
d D }|  r*|dd | ||P | j|||d\}}}z(t	|rO||j
i |jI dH }n	||j
i |j}| |W W  d   S  tyw   | jrttd n Y nw W d   dS 1 sw   Y  dS )	a  Async equivalent of :meth:`__call__` for use within existing event loops.

        This method should be used when you're already in an async context
        (e.g., Jupyter notebooks, existing async applications) and need to
        execute a Cyclopts command without creating a new event loop.

        Parameters
        ----------
        tokens : None | str | Iterable[str]
            Either a string, or a list of strings to launch a command.
            Defaults to ``sys.argv[1:]``.
        console: ~rich.console.Console
            Console to print help and runtime Cyclopts errors.
            If not provided, follows the resolution order defined in :attr:`App.console`.
        error_console: ~rich.console.Console
            Console to print error messages.
            If not provided, follows the resolution order defined in :attr:`App.error_console`.
        print_error: bool | None
            Print a rich-formatted error on error.
            If :obj:`None`, inherits from :attr:`App.print_error`, eventually defaulting to :obj:`True`.
        exit_on_error: bool | None
            If there is an error parsing the CLI tokens invoke ``sys.exit(1)``.
            Otherwise, continue to raise the exception.
            If :obj:`None`, inherits from :attr:`App.exit_on_error`, eventually defaulting to :obj:`True`.
        help_on_error: bool | None
            Prints the help-page before printing an error.
            If :obj:`None`, inherits from :attr:`App.help_on_error`, eventually defaulting to :obj:`False`.
        verbose: bool | None
            Populate exception strings with more information intended for developers.
            If :obj:`None`, inherits from :attr:`App.verbose`, eventually defaulting to :obj:`False`.
        end_of_options_delimiter: str | None
            All tokens after this delimiter will be force-interpreted as positional arguments.
            If :obj:`None`, inherits from :attr:`App.end_of_options_delimiter`, eventually defaulting to POSIX-standard ``"--"``.
            Set to an empty string to disable.
        backend: Literal["asyncio", "trio"] | None
            Override the async backend to use (if an async command is invoked).
            If :obj:`None`, inherits from :attr:`App.backend`, eventually defaulting to "asyncio".
            If passing backend="trio", ensure trio is installed via the extra: `cyclopts[trio]`.
        result_action: ResultAction | None
            Controls how command return values are handled. Can be a predefined literal string
            or a custom callable that takes the result and returns a processed value.
            If :obj:`None`, inherits from :attr:`App.result_action`, eventually defaulting to "print_non_int_return_int_as_exit_code".
            See :attr:`App.result_action` for available modes.

        Returns
        -------
        return_value: Any
            The value the command function returns.

        Examples
        --------
        .. code-block:: python

            import asyncio
            from cyclopts import App

            app = App()


            @app.command
            async def my_async_command():
                await asyncio.sleep(1)
                return "Done!"


            # In an async context (e.g., Jupyter notebook or existing async app):
            async def main():
                result = await app.run_async(["my-async-command"])
                print(result)  # Prints: Done!


            asyncio.run(main())
        Nc                 S   r  rd   rK   r  rK   rK   rL   r    r  z!App.run_async.<locals>.<dictcomp>r  r   r  r  r  )rz  r{  r    r  r  rU  r   r  rT   rg   r  rq   r  r  r   r   r  )r   r'  r   r   r   r   r   r   r   r   r   r`  r   rD   ry   rJ   rK   rK   rL   	run_asyncN  sL   W
	

"zApp.run_asyncrp  )r   c                C   s  ddl m}m} ddlm} t|}| |\}}}|d }	d|i}
| j||
d |	j}|	j	du r8|| |}n|	j	rA|	j	d }nd}|	jj
d	td
}||	|}| ||}|	jj
d| d
}t|drm|||j| n|rt|| t|dr|||j| n|r|| |D ]\}}|r|jnd}|du r|}td|}|||j| q|	j
d }rddl m} |  |j||d}|| W d   dS W d   dS 1 sw   Y  dS )a  Print the help page.

        Parameters
        ----------
        tokens: None | str | Iterable[str]
            Tokens to interpret for traversing the application command structure.
            If not provided, defaults to ``sys.argv``.
        console: ~rich.console.Console
            Console to print help and runtime Cyclopts errors.
            If not provided, follows the resolution order defined in :attr:`App.console`.
        r   )
format_docformat_usage)DefaultFormatterr(  r   r_  N
r   r  r   render_usagerender_descriptionr?   r   r  r  )r
  r  r  cyclopts.help.formattersr  r    r=  r   r   r   r   r  _assemble_help_panelshasattrr  optionsr  r  r   r   r  r  )r   r'  r   r  r  r  r7  r,  ry   executing_appr`  r   r   descriptionhelp_panels_with_groupsdefault_formatterr   panel	formatterr   r  epiloguerK   rK   rL   r     sN   






("zApp.help_printr)   r>   c           #   
   C   s  ddl m} ddl m} ddlm}m}m}m} | |\}	}
}|
d }|j	
d|t}i }t|D ]V}t|D ]O\}}|js@q8z	||j \}}W n ty`   ||jdd}||f||j< Y nw |jr}|j|j|d	d
}|jrz||j| ||_n||_|j|||d q8q2| |
}|D ]}|jsq|jd	d}|j	
dpd}tdd |D }|D ](}|D ]#}||	|}t|jjtsJ t|jtg |jj|R d|_qq|j D ]I}|jsq|j!|d}|sq|"|jd\}}||||}|rd|_#|j|j |_|jr|jr||j| |j|_n|j|_||f||j< qqdd |$ D }dd |$ D }g }t%||\} }!t&| |!ddD ]\}}"|"'  |"j#dkrZ|"(  |)||"f qH|S )Nr   )r)   )NewLine)r>   r  create_parameter_help_panelformat_command_entriesr(  r   r   )titler	  T)r	  force_empty_endr  )r\  r   rK   c                 s   s$    | ]}t |tr|jr|V  qd S rd   )r^   r"   r   rg  rK   rK   rL   ri  S  s   " z,App._assemble_help_panels.<locals>.<genexpr>)env_var)r   NN	parameterc                 S      g | ]}|d  qS )r   rK   rg  rK   rK   rL   r/  u      z-App._assemble_help_panels.<locals>.<listcomp>c                 S   r  )r0  rK   rg  rK   rK   rL   r/  v  r  F)strict)*r   r)   r  r
  r>   r  r  r  r=  r   r   r  r   r+   r   r   r   r   r  r  entriesr)  rB  r   rG  r6  _convert_argumentr^   r  r  r-   r^  groupsr  r   r	  r?  r*   zip_remove_duplicates_sortr   )#r   r'  r   	RichGroupr  r>   r  r  r  r7  r>  ry   rh  panelsr   r   apps_with_namescommand_panel
group_helpapps_for_paramsrK  configsenv_configsrs  
env_configr  group_argument_collectionexisting_panel	new_panelr  help_panelsr   sorted_groupssorted_panels
help_panelrK   rK   rL   r    s   

zApp._assemble_help_panelsrF   r0  output_formatr=   	recursiveinclude_hiddenheading_levelflatten_commandsc                 C   s   ddl m}m}m} ddlm}	 ||}|dkr#|| ||||d}
|
S |dkr2|	| ||||d}
|
S |dkr@|| ||||dd	}
|
S )
a  Generate documentation for this CLI application.

        Parameters
        ----------
        output_format : DocFormat
            Output format for the documentation. Accepts "markdown"/"md", "html"/"htm",
            or "rst"/"rest"/"restructuredtext". Default is "markdown".
        recursive : bool
            If True, generate documentation for all subcommands recursively.
            Default is True.
        include_hidden : bool
            If True, include hidden commands/parameters in documentation.
            Default is False.
        heading_level : int
            Starting heading level for the main application title.
            Default is 1 (single # for markdown, = for RST).
        flatten_commands : bool
            If True, generate all commands at the same heading level instead of nested.
            Default is False.

        Returns
        -------
        str
            The generated documentation.

        Raises
        ------
        ValueError
            If an unsupported output format is specified.

        Examples
        --------
        >>> app = App(name="myapp", help="My CLI Application")
        >>> docs = app.generate_docs()  # Generate markdown as string
        >>> html_docs = app.generate_docs(output_format="html")  # Generate HTML
        >>> rst_docs = app.generate_docs(output_format="rst")  # Generate RST
        >>> # To write to file, caller can do:
        >>> # Path("docs/cli.md").write_text(docs)
        r   )generate_markdown_docsgenerate_rst_docsnormalize_format)generate_html_docsrF   )r  r  r  r  htmlr   F)r  r  r  r  no_root_title)cyclopts.docsr  r  r  cyclopts.docs.htmlr  )r   r  r  r  r  r  r  r  r  r  r   rK   rK   rL   generate_docs  s>   /	zApp.generate_docs)	prog_nameshellr  r  )zshbashfishc                C   s   |du r| j stdt| j tr| j d n| j }|du r&ddlm} | }|dkr5ddlm} || |S |dkrDddlm} || |S |dkrSddl	m} || |S td	| )
a  Generate shell completion script for this application.

        Parameters
        ----------
        prog_name : str | None
            Program name for completion. If None, uses first name from app.name.
        shell : Literal["zsh", "bash", "fish"] | None
            Shell type. If None, automatically detects current shell.
            Supported shells: "zsh", "bash", "fish".

        Returns
        -------
        str
            Complete shell completion script.

        Examples
        --------
        Auto-detect shell and generate completion:

        >>> app = App(name="myapp")
        >>> script = app.generate_completion()
        >>> Path("_myapp").write_text(script)

        Explicitly specify shell type:

        >>> script = app.generate_completion(shell="zsh")

        Raises
        ------
        ValueError
            If app has no name or shell type is unsupported.
        ShellDetectionError
            If shell is None and auto-detection fails.
        Nz2App must have a name to generate completion scriptr   detect_shellr  )generate_completion_scriptr  r  zUnsupported shell: )
r   rI   r^   r6  cyclopts.completionr  cyclopts.completion.zshr  cyclopts.completion.bashcyclopts.completion.fish)r   r  r  r  r  rK   rK   rL   generate_completion  s"   (


zApp.generate_completion)r  outputadd_to_startupr  r  c                C   s   ddl m} |du r| }ddlm}m} | j|d}|du r'||| jd }|jjddd |	| |rC|dv rC||| jd | |S )	aO  Install shell completion script to appropriate location.

        Generates and writes the completion script to a shell-specific location.

        Parameters
        ----------
        shell : Literal["zsh", "bash", "fish"] | None
            Shell type for completion. If not specified, attempts to auto-detect current shell.
        output : Path | None
            Output path for the completion script. If not specified, uses shell-specific default:
            - zsh: ~/.zsh/completions/_<prog_name>
            - bash: ~/.local/share/bash-completion/completions/<prog_name>
            - fish: ~/.config/fish/completions/<prog_name>.fish
        add_to_startup : bool
            If True (default), adds source line to shell RC file to ensure completion is loaded.
            Set to False if completions are already configured to auto-load.

        Returns
        -------
        Path
            Path where the completion script was installed.

        Examples
        --------
        Auto-detect shell and install:

        >>> app = App(name="myapp")
        >>> path = app.install_completion()

        Install for specific shell:

        >>> path = app.install_completion(shell="zsh")

        Install to custom path:

        >>> path = app.install_completion(output=Path("/custom/path"))

        Install without modifying RC files:

        >>> path = app.install_completion(shell="bash", add_to_startup=False)

        Raises
        ------
        ShellDetectionError
            If shell is None and auto-detection fails.
        ValueError
            If shell type is unsupported.
        r   r  N)add_to_rc_fileget_default_completion_path)r  T)parentsexist_ok)r  r  )
cyclopts.completion.detectr  cyclopts.completion.installr  r  r  r   parentmkdir
write_text)r   r  r  r  r  r  r  script_contentrK   rK   rL   install_completion	  s   7
zApp.install_completion--install-completionc                 K   s2   ddl m} || j|}| j|fd|i| dS )a  Register a command for installing shell completion.

        This is a convenience method that creates a command which calls
        :meth:`install_completion`. For more control over the command
        implementation, users can manually define their own command.

        Parameters
        ----------
        name : str | Iterable[str]
            Command name(s) for the install completion command.
            Defaults to "--install-completion".
        add_to_startup : bool
            If True (default), adds source line to shell RC file to ensure completion is loaded.
            Set to False if completions are already configured to auto-load.
        **kwargs
            Additional keyword arguments to pass to :meth:`command`.
            Can be used to customize the command registration (e.g., `help`, `group`, `help_flags`, `version_flags`).

        Examples
        --------
        Register install-completion command:

        >>> app = App(name="myapp")
        >>> app.register_install_completion_command()
        >>> app()  # Now responds to: myapp --install-completion

        Use a custom command name:

        >>> app.register_install_completion_command(name="--setup-completion")

        Customize help text:

        >>> app.register_install_completion_command(help="Install shell completion for myapp.")

        Customize command registration:

        >>> app.register_install_completion_command(group="Setup", help_flags=[])

        Install without modifying RC files:

        >>> app.register_install_completion_command(add_to_startup=False)

        See Also
        --------
        install_completion : The underlying method that performs the installation.
        r   )!create_install_completion_commandr   N)r  r  r  r   )r   r   r  rq   r  
command_fnrK   rK   rL   #register_install_completion_commandc	  s   4z'App.register_install_completion_command$ promptquit
dispatcherzConsole | Nonec                 K   sP  t jdkr
td ntd |du rddg}t|tr|g}dd }|du r(|}i }	|dur2||	d	< |dur:||	d
< 	 zt|}
W n
 tyK   Y dS w t|
}|sSq:|d |v r[dS z4| ||	$ | j	|f||d|\}}}||||}| j
|dd W d   n1 sw   Y  W n ty   Y n ty   tt  Y nw q;)a  Create a blocking, interactive shell.

        All registered commands can be executed in the shell.

        Parameters
        ----------
        prompt: str
            Shell prompt. Defaults to ``"$ "``.
        quit: str | Iterable[str]
            String or list of strings that will cause the shell to exit and this method to return.
            Defaults to ``["q", "quit"]``.
        dispatcher: Dispatcher | None
            Optional function that subsequently invokes the command.
            The ``dispatcher`` function must have signature:

            .. code-block:: python

                def dispatcher(command: Callable, bound: inspect.BoundArguments, ignored: dict[str, Any]) -> Any:
                    return command(*bound.args, **bound.kwargs)

            The above is the default dispatcher implementation.
        console: Console | None
            Rich Console to use for output. If :obj:`None`, uses :attr:`App.console`.
        exit_on_error: bool
            Whether to call ``sys.exit`` on parsing errors. Defaults to :obj:`False`.
        result_action: ResultAction | None
            How to handle command return values in the interactive shell.
            Defaults to ``"print_non_int_return_int_as_exit_code"`` which prints non-int results
            and returns int/bool as exit codes without calling sys.exit.
            If :obj:`None`, inherits from :attr:`App.result_action`.
        `**kwargs`
            Get passed along to :meth:`parse_args`.
        posixz(Interactive shell. Press Ctrl-D to exit.z:Interactive shell. Press Ctrl-Z followed by Enter to exit.Nqr  c                 S   s   | |j i |jS rd   )r  rq   )r   rD   ry   rK   rK   rL   default_dispatcher	  s   z1App.interactive_shell.<locals>.default_dispatcherr   r   Tr   )r   r   %print_non_int_return_int_as_exit_coder  )osr   r  r^   r   inputEOFErrorr    r   r  r  r$   rH  	traceback
format_exc)r   r  r  r  r   r   r   rq   r   r`  
user_inputr'  r   rD   rb  rJ   rK   rK   rL   interactive_shell	  sZ   
+

zApp.interactive_shellprint_non_int_sys_exitrJ   r  c                    s6   ddl m} tt jjd|d}||| fddS )a  Handle command result based on result_action.

        Parameters
        ----------
        result : Any
            The command's return value.
        fallback : ResultAction
            The fallback result_action if none is configured. Defaults to "print_non_int_sys_exit".

        Returns
        -------
        Any
            Processed result based on action (may call sys.exit() and not return).
        r   )handle_result_actionr   r  c                    s    j | S rd   )r   r  ra   r   rK   rL   <lambda>
  s    z+App._handle_result_action.<locals>.<lambda>)cyclopts._result_actionr
  r   r@   r   r   )r   rJ   r  r
  actionrK   r   rL   r  	  s   zApp._handle_result_actionrj   c                 C   s   | j |j  dS )a   Copy over all commands from another :class:`App`.

        Commands from the meta app will **not** be copied over.

        Parameters
        ----------
        app: cyclopts.App
            All commands from this application will be copied over.
        N)r   r   )r   rj   rK   rK   rL   r   
  s   
z
App.updatec                 C   sx   i }| j D ]}|jsqt| |j}t|t|jks||jkr$|||j< qddd | D }t| j	 d| dS )zOnly shows non-default values.r1  c                 s   s"    | ]\}}| d |V  qdS )ru  NrK   r  rK   rK   rL   ri  '
  s     zApp.__repr__.<locals>.<genexpr>())
__attrs_attrs__r   getattrr   r$  r   r   r3  r  rO   )r   non_defaultsar  r}  rK   rK   rL   __repr__
  s   

zApp.__repr__)rH   r<   )r   rd   )T)rH   r}   )rH   r_   r  )rF   TFr0  F)r  T)r  NNNFN)r	  rj   r_   )rO   rP   rQ   r   r5   r   r   r6  __annotations__r   r   r8   r   rc   r   r   r   r   r-   r   r   r   r   rf   r   r   r   boolr   r   r   r   r   r   r   r   r   r   r)   r   ro   rn   rm   r7   r   r   r6   r   r   r   r   r   r   r   r4   r   r   rM   r   r@   rA   r   r   r   r   r   r   r1   r   r   r$  r   r   r   r   r   r   r   propertyr   setterr   r   rt   rs   rr   r   r   r   r   r   r   r   r   r  r  r   ri   rh   r  r  r  r  r  r  r   r#  r   r=  r   rB  r5  r   rC   objectr   r   rG  rT   BoundArgumentsrc  ra  r  r  r  r  r   r  intr  r  r   r  r  r/   r  r  r   r  rK   rK   rK   rL   r_     s  
 &" 4*""
	

















	5


( )
v"%A

 	
0
%$
7&
 	

k	


e	


 
H
l
W

D

N

;	
\c              	   C   s   d }|rt t | |}W d    n1 sw   Y  |D ]-}t t | |}|d u s3||k r=	 W d     |S W d    n1 sGw   Y  qd }|S rd   )r   rI   index)r'  r   r   delimiter_index	help_flagr  rK   rK   rL   r|  +
  s"   


r|  c                   @   s   e Zd ZdZdZdS )TestFrameworkrx   pytestN)rO   rP   rQ   UNKNOWNPYTESTrK   rK   rK   rL   r   <
  s    r   c                   C   s&   dt jv rtjddurtjS tjS )zDetects if we are currently being ran in a test framework.

    Returns
    -------
    TestFramework
        Name of the testing framework. Returns an empty string if not testing
        framework discovered.
    r!  PYTEST_VERSIONN)r   r   r  environr   r   r#  r"  rK   rK   rK   rL   r{  A
  s   r{  	frameworkc                 C   s   | t jkrdS ddl}t D ]l}|j}|j}t|}|du s$|du r%q|j	dd }|dkr2qd|j
vr8q|j
d }i |j|j
}g }	| D ]\}
}||u rX|	|
 qKt|	dkrbd}
n|	d }
d| j d	|
 d
}|jt|dd  dS dS )a  Log a warning message for a given testing framework.

    Intended to catch developers invoking their app during unit-tests
    without providing commands and erroneously reading from :obj:`sys.argv`.

    TO ONLY BE CALLED WITHIN A CYCLOPTS.APP METHOD.
    Nr   rR   rS   r   r0  rj   zGCyclopts application invoked without tokens under unit-test framework "z". Did you mean "z([])"?r9   )
stacklevel)r   r"  warningsrT   rU   rW   f_backrV   rO   rX   f_localsr   r  r   r2  rG   warnUserWarning)r&  r(  rY   rW   r)  calling_modulecalling_module_namecalled_cyclopts_app_instancecandidate_variablesmatched_app_variablesvar_namevar_instancemessagerK   rK   rL   rz  T
  s8   
	



rz  )rj   r_   rl   r_   rH   N)TTr  ){r   rT   r  r   r  collections.abcr   r   r   r   r   
contextlibr   r   enumr	   r   r
   r   	itertoolsr   pathlibr   typesr   typingr   r   r   r   r   r   r   r   r   attrsr   r   r   cyclopts.annotationsr   cyclopts.app_stackr   cyclopts.argumentr   rF  r   r   r    cyclopts.command_specr!   cyclopts.config._envr"   cyclopts.exceptionsr#   r$   r%   r&   r'   r(   cyclopts.groupr)   r*   cyclopts.group_extractorsr+   cyclopts.panelr,   cyclopts.parameterr-   r.   cyclopts.protocolsr/   cyclopts.tokenr0   cyclopts.utilsr1   r2   r3   r4   r5   r6   r7   r8   version_infor   readliner   r<   cyclopts.docs.typesr=   r
  r>   cyclopts.help.protocolsr?   r  r@   rA   cyclopts._runrB   rC   rE   r  r6  rM   rH  rN   r\   rc   rk   rp   r   r   ru   r|   r   r   r   r_   r  r|  r   r{  rz  rK   rK   rK   rL   <module>   s    , (


*



(                  9