U
    6e:                     @   s  d Z ddlZddlZddlZddl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 ddlmZmZ ddlmZ ddlmZmZmZmZmZ ddlmZmZ dd	lmZ d
dddddddgZ G dd
 d
ej!Z"dddej#ej$dddfej%eee&  e'e'eee'eej! e'ee& d
ddZ(d)ej%eee&  e'eej! e'eee
 ej!f dddZ)ej#ej$dfe
ej!eee'ee& dddZ*ee& ee e'ee& dddZ+ej!ee
 ddd Z,e
ej!eee& d!d"d#Z-e
dd$d%dZ.ee
 dd&d'dZ/G d(d dZ0dS )*z
Dispatching
~~~~~~~~~~~
    N)GeneratorType)IOAnyCallableDictIteratorListOptionalTuple)add_commandsset_default_command)autocomplete)ATTR_EXPECTS_NAMESPACE_OBJECTATTR_WRAPPED_EXCEPTIONS!ATTR_WRAPPED_EXCEPTIONS_PROCESSORDEST_FUNCTIONPARSER_FORMATTER)CommandErrorDispatchingError)get_arg_specArghNamespacedispatchdispatch_commanddispatch_commandsparse_and_resolverun_endpoint_functionr   
EntryPointc                       sJ   e Zd ZdZdd fddZeedd fddZedd	d
Z	  Z
S )r   zC
    A namespace object which collects the stack of functions.
    Nreturnc                    s   t  j|| g | _d S N)super__init___functions_stack)selfargskwargs	__class__ /lib/python3.8/site-packages/argh/dispatching.pyr!   2   s    zArghNamespace.__init__)keyvaluer   c                    s(   |t kr| j| nt || d S r   )r   r"   appendr    __setattr__)r#   r*   r+   r&   r(   r)   r-   6   s    	zArghNamespace.__setattr__c                 C   s
   | j d S )N)r"   )r#   r(   r(   r)   get_functionD   s    zArghNamespace.get_function)__name__
__module____qualname____doc__r!   strr   r-   r   r/   __classcell__r(   r(   r&   r)   r   -   s   FT)
parserargvadd_help_command
completionoutput_fileerrors_file
raw_output	namespaceskip_unknown_argsr   c	                 C   sp   |r6t td |r6|d dkr6|d |d t| ||||d\}	}
|	s^| | dS t|	|
|||dS )a	  
    Parses given list of arguments using given parser, calls the relevant
    function and prints the result.

    Internally calls :func:`~argh.dispatching.parse_and_resolve` and then
    :func:`~argh.dispatching.run_endpoint_function`.

    :param parser:

        the ArgumentParser instance.

    :param argv:

        a list of strings representing the arguments. If `None`, ``sys.argv``
        is used instead. Default is `None`.

    :param add_help_command:

        if `True`, converts first positional argument "help" to a keyword
        argument so that ``help foo`` becomes ``foo --help`` and displays usage
        information for "foo". Default is `False`.

        .. versionchanged:: 0.30

           The default value is now ``False`` instead of ``True``.

        .. deprecated:: 0.30

           This argument will be removed in v.0.31.  The user is expected to
           use ``--help`` instead of ``help``.

    :param output_file:

        A file-like object for output. If `None`, the resulting lines are
        collected and returned as a string. Default is ``sys.stdout``.

    :param errors_file:

        Same as `output_file` but for ``sys.stderr``, and `None` is not accepted.

    :param raw_output:

        If `True`, results are written to the output file raw, without adding
        whitespaces or newlines between yielded strings. Default is `False`.

    :param completion:

        If `True`, shell tab completion is enabled. Default is `True`. (You
        will also need to install it.)  See :mod:`argh.completion`.

    :param skip_unknown_args:

        If `True`, unknown arguments do not cause an error
        (`ArgumentParser.parse_known_args` is used).

    :param namespace:

        An `argparse.Namespace`-like object.  By default an
        :class:`argh.dispatching.ArghNamespace` object is used.  Please note
        that support for combined default and nested functions may be broken
        if a different type of object is forced.

    By default the exceptions are not wrapped and will propagate. The only
    exception that is always wrapped is :class:`~argh.exceptions.CommandError`
    which is interpreted as an expected event so the traceback is hidden.
    You can also mark arbitrary exceptions as "wrappable" by using the
    :func:`~argh.decorators.wrap_errors` decorator.

    Wrapped exceptions, or other "expected errors" like parse failures,
    will cause a SystemExit to be raised.
    zwThe argument `add_help_command` in `dispatch()` is deprecated. The user is expected to type `--help` instead of `help`.r   helpz--help)r6   r9   r7   r=   r>   N)functionnamespace_objr:   r;   r<   )warningswarnDeprecationWarningpopr,   r   print_usager   )r6   r7   r8   r9   r:   r;   r<   r=   r>   Zendpoint_functionrA   r(   r(   r)   r   H   s4    T



)r6   r7   r9   r=   r>   r   c                 C   sh   |rt |  |dkr"tjdd }|s,t }|rJ| j||d\}}||_n| j||d}t|}||fS )z^
    .. versionadded:: 0.30

    Parses CLI arguments and resolves the endpoint function.
    N   )r=   )r   sysr7   r   parse_known_argsZ_unknown_args
parse_args _get_function_from_namespace_obj)r6   r7   r9   r=   r>   rA   Zunknown_argsr@   r(   r(   r)   r      s    )r@   rA   r:   r;   r<   r   c                 C   s   t | ||}t|||S )z
    .. versionadded:: 0.30

    Extracts arguments from the namespace object, calls the endpoint function
    and processes its output.
    )_execute_command_process_command_output)r@   rA   r:   r;   r<   linesr(   r(   r)   r      s    )rN   r:   r<   r   c                 C   sZ   |d krt  }n|}| D ] }|t| |s|d q|d krV|d | S d S )N
r   )ioStringIOwriter4   seekread)rN   r:   r<   Zout_ioliner(   r(   r)   rM      s    

rM   )rA   r   c              	   C   s^   t | tr4z|  }W qL ttfk
r0   Y d S X nt| tsBd S t| t}t|dsZd S |S )N__call__)
isinstancer   r/   AttributeError
IndexErrorhasattrr   getattr)rA   r@   r(   r(   r)   rK     s    




rK   )r@   rA   r;   r   c              
   #   s    fdd}t g}|t tg 7 }ttddd}z| }|D ]
}|V  q@W nv t|k
r } zTt t|}	|t|	| |d t|t r|j	dk	r|j	nd}
t
|
 W 5 d}~X Y nX dS )	a  
    Assumes that `function` is a callable.  Tries different approaches
    to call it (with `namespace_obj` or with ordinary signature).
    Yields the results line by line.

    If :class:`~argh.exceptions.CommandError` is raised, its message is
    written to the error file, and a SystemExit is raised.
    All other exceptions propagate unless marked as wrappable
    by :func:`wrap_errors`.
    c            
      3   s:  t tdr} ndd  t fddt D t}fdd|jD }t |dg }tfd	d|D }|jr||j 7 }t |d
t |dg }|rtg|j |jg | }tD ].} |}|	ds||krqt |||< qƈ||} t
| tttfr&| D ]}	|	V  qn| d k	r6| V  d S )NFc                 S   s   |  ddS )N-_)replace)r*   r(   r(   r)   	_flat_key:  s    z2_execute_command.<locals>._call.<locals>._flat_keyc                 3   s   | ]\}} ||fV  qd S r   r(   ).0kv)r_   r(   r)   	<genexpr>=  s     z2_execute_command.<locals>._call.<locals>.<genexpr>c                    s   g | ]} | qS r(   r(   r`   ra   	all_inputr(   r)   
<listcomp>D  s     z3_execute_command.<locals>._call.<locals>.<listcomp>Z
kwonlyargsc                 3   s   | ]}| | fV  qd S r   r(   rd   re   r(   r)   rc   F  s     varkwkeywordsr]   )r[   r   dictvarsitemsr   r$   Zvarargsr   
startswithrW   r   listtuple)
resultspecZ
positionalZkwonlyri   rh   Z
not_kwargsra   Znormalized_krU   r@   rA   )r_   rf   r)   _call4  s0    


z_execute_command.<locals>._call)excr   c                 S   s   | j j d|  S )Nz: )r'   r0   )rt   r(   r(   r)   default_exception_processore  s    z5_execute_command.<locals>.default_exception_processorrO   NrG   )r   r[   r   	Exceptionr4   ro   r   rR   rW   coderH   exit)r@   rA   r;   rs   Zwrappable_exceptionsru   rp   rU   rt   Z	processorrw   r(   rr   r)   rL   %  s$    .  
rL   r@   r   c                 O   s*   t jtd}t||  t|f|| dS )a  
    A wrapper for :func:`dispatch` that creates a one-command parser.
    Uses :attr:`argh.constants.PARSER_FORMATTER`.

    This::

        dispatch_command(foo)

    ...is a shortcut for::

        parser = ArgumentParser()
        set_default_command(parser, foo)
        dispatch(parser)

    This function can be also used as a decorator::

        @dispatch_command
        def main(foo: int = 123) -> int:
            return foo + 1

    formatter_classN)argparseArgumentParserr   r   r   )r@   r$   r%   r6   r(   r(   r)   r   z  s    
)	functionsr   c                 O   s*   t jtd}t||  t|f|| dS )aL  
    A wrapper for :func:`dispatch` that creates a parser, adds commands to
    the parser and dispatches them.
    Uses :attr:`PARSER_FORMATTER`.

    This::

        dispatch_commands([foo, bar])

    ...is a shortcut for::

        parser = ArgumentParser()
        add_commands(parser, [foo, bar])
        dispatch(parser)

    rz   N)r|   r}   r   r   r   )r~   r$   r%   r6   r(   r(   r)   r     s    
c                   @   sf   e Zd ZdZdee eeeef  ddddZdee	 dddZ
e	dd	d
dZddddZdS )r   a  
    An object to which functions can be attached and then dispatched.

    When called with an argument, the argument (a function) is registered
    at this entry point as a command.

    When called without an argument, dispatching is triggered with all
    previously registered commands.

    Usage::

        from argh import EntryPoint

        app = EntryPoint("main", {"description": "This is a cool app"})

        @app
        def ls() -> None:
            for i in range(10):
                print i

        @app
        def greet() -> None:
            print "hello"

        if __name__ == "__main__":
            app()

    N)nameparser_kwargsr   c                 C   s   |pd| _ g | _|pi | _d S )NZunnamed)r   commandsr   )r#   r   r   r(   r(   r)   r!     s    
zEntryPoint.__init__)r@   c                 C   s   |r|  | |S |  S r   )_register_command	_dispatchr#   r@   r(   r(   r)   rV     s    
zEntryPoint.__call__ry   c                 C   s   | j | d S r   )r   r,   r   r(   r(   r)   r     s    zEntryPoint._register_commandr   c                 C   s>   | j std| j dtjf | j}t|| j  t| d S )Nzno commands for entry point "")r   r   r   r|   r}   r   r   r   )r#   r6   r(   r(   r)   r     s
    zEntryPoint._dispatch)NN)N)r0   r1   r2   r3   r	   r4   r   r   r!   r   rV   r   r   r(   r(   r(   r)   r     s       )NTNF)1r3   r|   rP   rH   rB   typesr   typingr   r   r   r   r   r   r	   r
   Zargh.assemblingr   r   Zargh.completionr   Zargh.constantsr   r   r   r   r   Zargh.exceptionsr   r   Z
argh.utilsr   __all__	Namespacer   stdoutstderrr}   r4   boolr   r   r   rM   rK   rL   r   r   r   r(   r(   r(   r)   <module>
   s   (
v    
%     U