U
    6e-U                  
   @   s  d Z ddl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mZmZmZmZmZmZ ddlmZ ddl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# ddddgZ$G dd de	Z%e%j&feee% ee dddZ'eee(ef dddZ)e%j&fee%ddddZ*ee+ddddZ,ee ee e+ee dddZ-d)ee( e(e+dd d!Z.e%j&dddfeee e%ee( eee(ef  eee(ef  dd"d#dZ/eee(e0f d$d%d&Z1ee(ee dd'd(dZ2dS )*z^
Assembling
~~~~~~~~~~

Functions and classes to properly assemble your commands in a parser.
    N)OPTIONALZERO_OR_MOREArgumentParser)OrderedDict)Enum)AnyCallableDictIteratorListOptionalTuple)COMPLETION_ENABLED)ATTR_ALIASES	ATTR_ARGSATTR_EXPECTS_NAMESPACE_OBJECT	ATTR_NAMEDEFAULT_ARGUMENT_TEMPLATEDEST_FUNCTIONPARSER_FORMATTER)
NotDefinedParserAddArgumentSpec)AssemblingError)get_arg_specget_subparsersset_default_commandadd_commandsadd_subcommandsNameMappingPolicyc                   @   s   e Zd ZdZdZdZdS )r   a:  
    Represents possible approaches to treat default values when inferring argument
    specification from function signature.

    * `BY_NAME_IF_KWONLY` is the default and recommended approach introduced
      in v0.30.  It enables fine control over two aspects:

      * positional vs named;
      * required vs optional.

      "Normal" arguments are identified by position, "kwonly" are identified by
      name, regardless of the presence of default values.  A positional with a
      default value becomes optional but still positional (``nargs=OPTIONAL``).
      A kwonly argument without a default value becomes a required named
      argument.

      Example::

          def func(alpha, beta=1, *, gamma, delta=2): ...

      is equivalent to::

          prog alpha [beta] --gamma [--delta DELTA]

      That is, ``alpha`` and ``--gamma`` are mandatory while ``beta`` and
      ``--delta`` are optional (they have default values).

    * `BY_NAME_IF_HAS_DEFAULT` is very close to the the legacy approach
      (pre-v0.30).  If a function argument has a default value, it becomes an
      "option" (called by name, like ``--foo``); otherwise it's treated as a
      positional argument.

      Example::

          def func(alpha, beta=1, *, gamma, delta=2): ...

      is equivalent to::

          prog [--beta BETA] [--delta DELTA] alpha gamma

      That is, ``alpha`` and ``gamma`` are mandatory and positional, while
      ``--beta`` and ``--delta`` are optional (they have default values).  Note
      that it's impossible to have an optional positional or a mandatory named
      argument.

      The difference between this policy and the behaviour of Argh before
      v0.30 is in the treatment of kwonly arguments without default values:
      they used to become ``--foo FOO`` (required) but for the sake of
      simplicity they are treated as positionals.  If you are already using
      kwonly args, please consider the better suited policy `BY_NAME_IF_KWONLY`
      instead.

    It is recommended to migrate any older code to `BY_NAME_IF_KWONLY`.

    .. versionadded:: 0.30
    z6specify CLI argument by name if it has a default valuez4specify CLI argument by name if it comes from kwonlyN)__name__
__module____qualname____doc__ZBY_NAME_IF_HAS_DEFAULTBY_NAME_IF_KWONLY r$   r$   .lib/python3.8/site-packages/argh/assembling.pyr   ,   s   9)functionname_mapping_policyreturnc                 #   s  t | tdrd S |tkr&td| t| }ttt|jt|j	pFt
 }tt||j }dd |D tfddtD t
fddD  ttt tt f d fd	d
}|jD ]T}||\}}||t}	t|||	d}
|	tkr|tjkrt|
_n||
_|
V  q|jD ]~}||\}}|jrR||jkrR|j| }	nt}	t|||	d}
|tjkr||
_|	tkrd|
_n|	tkr||
_|
V  q"|jrt|j|jddgtdV  d S )NFzUnknown name mapping policy c                 S   s   g | ]}|d  qS )r   r$   ).0ar$   r$   r%   
<listcomp>   s     z0infer_argspecs_from_function.<locals>.<listcomp>c                 3   s   | ]}|  |fV  qd S N)countr)   char)named_arg_charsr$   r%   	<genexpr>   s    z/infer_argspecs_from_function.<locals>.<genexpr>c                 3   s   | ]}d  | k r|V  qdS )   Nr$   r.   )named_arg_char_countsr$   r%   r1      s     )r(   c                    sP   |  dd}|g}| d  k}|r<d|d  d| g}nd| g}||fS )N_-r   z--)replace)arg_nameZcliified_arg_namepositionalsZcan_have_short_optoptions)conflicting_optsr$   r%   _make_cli_arg_names_options   s    zAinfer_argspecs_from_function.<locals>._make_cli_arg_names_options)func_arg_namecli_arg_namesdefault_valueTr4   r5   )r<   r=   nargs)getattrr   r   NotImplementedErrorr   dictzipreversedargsdefaultstuplesetlistZ
kwonlyargsr   r   strgetr   r   r#   r   r?   r=   ZkwonlydefaultsZis_requiredZvarargsr6   r   )r&   r'   	func_specZdefault_by_arg_nameZ
named_argsr;   r7   Zcli_arg_names_positionalZcli_arg_names_optionsr>   Zarg_specr$   )r:   r3   r0   r%   infer_argspecs_from_functionj   sr    "





rM   )parser_add_argument_specr(   c                 C   s   | j }i }| jd d }d}| j}|dtfkrt|tr`|s|ddkr|rVdnd|d< n*|ddkr|dd	|krt||d< |d
rdt	|t	| krt|d
 d |d< |S )u  
    Given an argument specification, returns types, actions, etc. that could be
    guessed from it:

    * ``default=3`` → ``type=int``

      TODO: deprecate in favour of ``foo: int = 3`` in func signature.

    * ``choices=[3]`` → ``type=int``

      TODO: deprecate in favour of ``foo: int`` in func signature.

    * ``type=bool`` → ``action="store_false"`` or ``action="store_true"``
      (if action was not explicitly defined).

    r   r5   )storeappendNactionstore_false
store_truetyperO   choices)
other_add_parser_kwargsr=   
startswithr>   r   
isinstanceboolrK   rT   rI   )rN   rV   ZguessedZis_positionalZTYPE_AWARE_ACTIONSr>   r$   r$   r%   +guess_extra_parser_add_argument_spec_kwargs   s"    
rZ   c                 C   sp  t |}t|j}t|tg }tt||d}|rJ|sJ|sJt|j d|sT|}nTzt	|||d}W n@ tk
r } z"t
| t|j d| |W 5 d}~X Y nX |D ]}	t|	| jd z| j|	j|	 }
W nT tk
r( } z4d|	j}t|j d|	j d	| d| |W 5 d}~X Y nX tr|	jr|	j|
_qt|}|r\| js\|| _| jf t|i dS )
a  
    Sets default command (i.e. a function) for given parser.

    If `parser.description` is empty and the function has a docstring,
    it is used as the description.

    :param function:

        The function to use as the command.

    :name_mapping_policy:

        The policy to use when mapping function arguments onto CLI arguments.
        See :class:`.NameMappingPolicy`.

        .. versionadded:: 0.30

    .. note::

       If there are both explicitly declared arguments (e.g. via
       :func:`~argh.decorators.arg`) and ones inferred from the function
       signature, declared ones will be merged into inferred ones.
       If an argument does not conform to the function signature,
       `AssemblingError` is raised.

    .. note::

       If the parser was created with ``add_help=True`` (which is by default),
       option name ``-h`` is silently removed from any argument.

    r'   zW: cannot extend argument declarations for an endpoint function that takes no arguments.)inferred_argsdeclared_args	has_varkwz: Nspecparser_adds_help_arg/z: cannot add 'z' as )r   rY   Zvarkwr@   r   rI   rM   r   r   !_merge_inferred_and_declared_argsprint _extend_parser_add_argument_specadd_helpadd_argumentr=   Zget_all_kwargs	Exceptionjoinr<   r   Z	completerinspectZgetdocdescriptionset_defaultsr   )parserr&   r'   rL   r^   r]   r\   Zparser_add_argument_specsexcr`   rQ   Zerr_cli_argsZ	docstringr$   r$   r%   r      s`    $



( 


 )r`   ra   r(   c                 C   sL   | j t|  d| j kr(| j jtd |rHd| jkrHdd | jD | _d S )Nhelpro   -hc                 S   s   g | ]}|d kr|qS )rq   r$   )r)   namer$   r$   r%   r+   n  s      z4_extend_parser_add_argument_spec.<locals>.<listcomp>)rV   updaterZ   r   r=   r_   r$   r$   r%   re   ]  s    
re   )r\   r]   r^   r(   c              	      s   t   | D ]}| |j< q
|D ]}|}|j}| krt|j}t | j}||krddd}|| }	|| }
td| d|	 d|
 d | | q|r| |< q fdd	 D }d
|j}d
dd	 |D }td| d| qt  S )NZ
positionalZoptional)TFz
argument "z" declared as z (in function signature) and z (via decorator). If you've just migrated from Argh v.0.29, please check the new default NameMappingPolicy. Perhaps you need to replace `func(x=1)` with `func(*, x=1)`?c                 3   s   | ]} | j V  qd S r,   )r=   r)   xZspecs_by_func_arg_namer$   r%   r1     s   z4_merge_inferred_and_declared_args.<locals>.<genexpr>z, c                 s   s   | ]}d  |V  qdS )rb   N)ri   rt   r$   r$   r%   r1     s     z	argument z" does not fit function signature: )	r   r<   _is_positionalr=   r   rs   ri   rI   values)r\   r]   r^   rN   Zdeclared_specr<   Zdecl_positionalZinfr_positionalZkindsZkind_inferredZkind_declaredZdest_option_stringsZ	msg_flagsZmsg_signaturer$   rv   r%   rc   q  sB    





rc   r5   )rE   prefix_charsr(   c                 C   s2   | r| d st d| d d t|r.dS dS )Nr   zExpected at least one argumentFT)
ValueErrorrW   rG   )rE   ry   r$   r$   r%   rw     s
    rw   )rm   	functionsr'   
group_namegroup_kwargsfunc_kwargsr(   c                 C   s   |pi }t | dd}|r:|j||dd}|jf |}n|rFtd|D ]:}t|\}	}
|rh|
| |j|	f|
}t|||d qJdS )a  
    Adds given functions as commands to given parser.

    :param parser:

        an :class:`argparse.ArgumentParser` instance.

    :param functions:

        a list of functions. A subparser is created for each of them.
        If the function is decorated with :func:`~argh.decorators.arg`, the
        arguments are passed to :meth:`argparse.ArgumentParser.add_argument`.
        See also :func:`~argh.dispatching.dispatch` for requirements
        concerning function signatures. The command name is inferred from the
        function name. Note that the underscores in the name are replaced with
        hyphens, i.e. function name "foo_bar" becomes command name "foo-bar".

    :param name_mapping_policy:

        See :class:`argh.assembling.NameMappingPolicy`.

        .. versionadded:: 0.30

    :param group_name:

        an optional string representing the group of commands. For example, if
        a command named "hello" is added without the group name, it will be
        available as "prog.py hello"; if the group name if specified as "greet",
        then the command will be accessible as "prog.py greet hello". The
        group itself is not callable, so "prog.py greet" will fail and only
        display a help message.

    :param func_kwargs:

        a `dict` of keyword arguments to be passed to each nested ArgumentParser
        instance created per command (i.e. per function).  Members of this
        dictionary have the highest priority, so a function's docstring is
        overridden by a `help` in `func_kwargs` (if present).

    :param group_kwargs:

        a `dict` of keyword arguments to be passed to the nested ArgumentParser
        instance under given `group_name`.

    .. note::

        This function modifies the parser object. Generally side effects are
        bad practice but we don't seem to have any choice as ArgumentParser is
        pretty opaque.
        You may prefer :meth:`~argh.helpers.ArghParser.add_commands` for a bit
        more predictable API.

    .. note::

       An attempt to add commands to a parser which already has a default
       function (e.g. added with :func:`~argh.assembling.set_default_command`)
       results in `AssemblingError`.

    T)Zcreatetitlerp   z2`group_kwargs` only makes sense with `group_name`.r[   N)r   
add_parserrK   add_subparsersrz   _extract_command_meta_from_funcrs   r   )rm   r{   r'   r|   r}   r~   Zsubparsers_actionZsubsubparserfunccmd_namefunc_parser_kwargsZcommand_parserr$   r$   r%   r     s(    C 
  )r   r(   c                 C   s:   t | t| jdd}| jtd}t | tg |d< ||fS )Nr4   r5   )ro   formatter_classaliases)r@   r   r   r6   r"   r   r   )r   r   r   r$   r$   r%   r   /  s    r   )rm   r|   r{   r(   c                 K   s   t | |||d dS )a  
    A wrapper for :func:`add_commands`.

    These examples are equivalent::

        add_commands(
            parser,
            [get, put],
            group_name="db",
            group_kwargs={
                "title": "database commands",
                "help": "CRUD for our silly database"
            }
        )

        add_subcommands(
            parser,
            "db",
            [get, put],
            title="database commands",
            help="CRUD for our database"
        )

    )r|   r}   N)r   )rm   r|   r{   r}   r$   r$   r%   r   @  s    )r5   )3r"   rj   argparser   r   r   collectionsr   enumr   typingr   r   r	   r
   r   r   r   Zargh.completionr   Zargh.constantsr   r   r   r   r   r   r   Zargh.dtor   r   Zargh.exceptionsr   Z
argh.utilsr   r   __all__r   r#   rM   rJ   rZ   r   rY   re   rc   rw   r   rB   r   r   r$   r$   r$   r%   <module>
   s|   $$	Ba
5b Qe  