U
    42iRP                     @  sJ  d dl mZ d dlZd dlmZ d dlZd dlZd dlmZ d dlmZ d dlm	Z	 d dlm
Z
 d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlZd dlmZ d dlmZ dZG dd dZe Ze
G dd dZdddddZG dd deZG dd dZG dd dZG dd  d ejZ G d!d" d"ej!Z"dS )#    )annotationsN)gettext)Any)Callable)cast)final)List)Literal)Mapping)NoReturn)Sequence)
UsageError)check_ispytestZfile_or_dirc                   @  s   e Zd ZddddZdS )NotSetstrreturnc                 C  s   dS )Nz<notset> selfr   r   =/tmp/pip-unpacked-wheel-7n2p7kht/_pytest/config/argparsing.py__repr__   s    zNotSet.__repr__N)__name__
__module____qualname__r   r   r   r   r   r      s   r   c                   @  s   e Zd ZU dZdZded< d2dddddd	d
ddZdd	dddZd3dddddddZddd	dddZ	d4dddddd Z
d!d"d#d$Zd5dddd%d&d'd(Zd6ddddd)d*Zd7ddd+dd,d-Zdefddd.dd	d/d0d1ZdS )8ParserzParser for command line arguments and ini-file values.

    :ivar extra_info: Dict of generic param -> value to display in case
        there's an error processing the command line arguments.
    N
str | NoneprogF	_ispytestz!Callable[[Argument], None] | NoneboolNone)usage
processoptr   r   c                C  s@   t | td| dd| _g | _|| _|| _i | _g | _i | _d S )NzCustom optionsTparserr   )	r   OptionGroup
_anonymous_groups_processopt_usage_inidict	_ininames
extra_info)r   r"   r#   r   r   r   r   __init__,   s    zParser.__init__Argument)optionr   c                 C  s   | j r|jr|  | d S N)r)   dest)r   r0   r   r   r   processoption<   s    zParser.processoption r   r&   )namedescriptionafterr   c                 C  sj   | j D ]}|j|kr|  S qt||| dd}d}t| j D ]\}}|j|kr< qTq<| j |d | |S )a  Get (or create) a named option Group.

        :param name: Name of the option group.
        :param description: Long description for --help output.
        :param after: Name of another group, used for ordering --help output.
        :returns: The option group.

        The returned group object has an ``addoption`` method with the same
        signature as :func:`parser.addoption <pytest.Parser.addoption>` but
        will be shown in the respective group in the output of
        ``pytest --help``.
        Tr$   r      )r(   r5   r&   	enumerateinsert)r   r5   r6   r7   groupigrpr   r   r   getgroupA   s    



zParser.getgroupr   optsattrsr   c                 O  s   | j j|| dS )a  Register a command line option.

        :param opts:
            Option names, can be short or long options.
        :param attrs:
            Same attributes as the argparse library's :meth:`add_argument()
            <argparse.ArgumentParser.add_argument>` function accepts.

        After command line parsing, options are available on the pytest config
        object via ``config.option.NAME`` where ``NAME`` is usually set
        by passing a ``dest`` attribute, for example
        ``addoption("--long", dest="NAME", ...)``.
        N)r'   	addoption)r   r@   rA   r   r   r   rB   [   s    zParser.addoptionz Sequence[str | os.PathLike[str]]argparse.Namespace | Noneargparse.Namespaceargs	namespacer   c                 C  s>   ddl m} |  | _|| j dd |D }| jj||dS )Nr   )try_argcompletec                 S  s   g | ]}t |qS r   osfspath.0xr   r   r   
<listcomp>t   s     z Parser.parse.<locals>.<listcomp>rG   )_pytest._argcompleterH   
_getparser	optparser
parse_args)r   rF   rG   rH   strargsr   r   r   parsek   s
    

zParser.parseMyOptionParserr   c                 C  s   ddl m} t| | j| jd}| j| jf}|D ]H}|jr0|jpD|j	}|
|}|jD ] }| }| }	|j||	 qVq0|jtdd}
||
_|S )Nr   )filescompleter)r   *)nargs)rQ   rX   rW   r-   r   r(   r'   optionsr6   r5   add_argument_groupnamesrA   add_argumentFILE_OR_DIRZ	completer)r   rX   rS   groupsr;   descZarggroupr0   naZfile_or_dir_argr   r   r   rR   w   s    

zParser._getparser	list[str])rF   r0   rG   r   c                 C  sB   | j ||d}|j D ]\}}t||| qttt t|tS )NrP   )	rV   __dict__itemssetattrr   r   r   getattrr_   )r   rF   r0   rG   Zparsedoptionr5   valuer   r   r   parse_setoption   s    zParser.parse_setoptionc                 C  s   | j ||dd S )zbParse the known arguments at this point.

        :returns: An argparse namespace object.
        rP   r   )parse_known_and_unknown_args)r   rF   rG   r   r   r   parse_known_args   s    	zParser.parse_known_argsz$tuple[argparse.Namespace, list[str]]c                 C  s$   |   }dd |D }|j||dS )a  Parse the known arguments at this point, and also return the
        remaining unknown arguments.

        :returns:
            A tuple containing an argparse namespace object for the known
            arguments, and a list of the unknown arguments.
        c                 S  s   g | ]}t |qS r   rI   rL   r   r   r   rO      s     z7Parser.parse_known_and_unknown_args.<locals>.<listcomp>rP   )rR   rl   )r   rF   rG   rS   rU   r   r   r   rk      s    z#Parser.parse_known_and_unknown_argsKLiteral[('string', 'paths', 'pathlist', 'args', 'linelist', 'bool')] | None)r5   helptypedefaultr   c                 C  s<   |dkst |tkrt|}|||f| j|< | j| dS )aR  Register an ini-file option.

        :param name:
            Name of the ini-variable.
        :param type:
            Type of the variable. Can be:

                * ``string``: a string
                * ``bool``: a boolean
                * ``args``: a list of strings, separated as in a shell
                * ``linelist``: a list of strings, separated by line breaks
                * ``paths``: a list of :class:`pathlib.Path`, separated as in a shell
                * ``pathlist``: a list of ``py.path``, separated as in a shell

            For ``paths`` and ``pathlist`` types, they are considered relative to the ini-file.
            In case the execution is happening without an ini-file defined,
            they will be considered relative to the current working directory (for example with ``--override-ini``).

            .. versionadded:: 7.0
                The ``paths`` variable type.

            .. versionadded:: 8.1
                Use the current working directory to resolve ``paths`` and ``pathlist`` in the absence of an ini-file.

            Defaults to ``string`` if ``None`` or not passed.
        :param default:
            Default value if no ini-file option exists but is queried.

        The value of ini-variables can be retrieved via a call to
        :py:func:`config.getini(name) <pytest.Config.getini>`.
        )NstringpathspathlistrF   linelistr    N)AssertionErrorNOT_SETget_ini_default_for_typer+   r,   append)r   r5   rn   ro   rp   r   r   r   addini   s
    'zParser.addini)NN)r4   N)N)N)N)N)r   r   r   __doc__r   __annotations__r.   r3   r>   rB   rV   rR   rj   rl   rk   rv   ry   r   r   r   r   r   "   s0   
         r   rm   r   )ro   r   c                 C  s,   | dkrdS | dkrg S | dkr$dS dS dS )zp
    Used by addini to get the default value for a given ini-option type, when
    default is not supplied.
    Nr4   )rr   rs   rF   rt   r    Fr   )ro   r   r   r   rw      s    rw   c                   @  s0   e Zd ZdZddddddZddd	d
ZdS )ArgumentErrorzURaised if an Argument instance is created with invalid or
    inconsistent arguments.r   zArgument | strr!   )msgr0   r   c                 C  s   || _ t|| _d S r1   )r}   r   	option_id)r   r}   r0   r   r   r   r.      s    zArgumentError.__init__r   c                 C  s$   | j rd| j  d| j S | jS d S )Nzoption : )r~   r}   r   r   r   r   __str__   s    zArgumentError.__str__N)r   r   r   rz   r.   r   r   r   r   r   r|      s   r|   c                   @  s\   e Zd ZdZddddddZdd	d
dZdd	ddZdddddZdd	ddZdS )r/   zClass that mimics the necessary behaviour of optparse.Option.

    It's currently a least effort implementation and ignoring choices
    and integer prefixes.

    https://docs.python.org/3/library/optparse.html#optparse-standard-option-types
    r   r   r!   )r]   rA   r   c              
   O  s   || _ g | _g | _z|d | _W n tk
r4   Y nX z|d | _W n tk
rX   Y nX | | |d}|rz|| _nr| jr| jd dd 	dd| _nNz| jd d	d | _W n4 t
k
r } zd
| _td| |W 5 d}~X Y nX dS )z5Store params in private vars for use in add_argument.ro   rp   r2   r      N-_r8   z???zneed a long or short option)_attrs_short_opts
_long_optsro   KeyErrorrp   _set_opt_stringsgetr2   replace
IndexErrorr|   )r   r]   rA   r2   er   r   r   r.     s,    

zArgument.__init__rd   r   c                 C  s   | j | j S r1   )r   r   r   r   r   r   r]   #  s    zArgument.nameszMapping[str, Any]c              	   C  sN   d  }|| j |D ].}zt| || j|< W q tk
rD   Y qX q| jS )Nzdefault dest help)splitrx   r2   rh   r   AttributeError)r   rA   attrr   r   r   rA   &  s    zArgument.attrszSequence[str])r@   r   c                 C  s   |D ]}t |dk r(td|d| qt |dkrl|d dkrL|d dks^td|d| | j| q|dd d	kr|d dkstd
|d| | j| qdS )zhDirectly from optparse.

        Might not be necessary as this is passed to argparse later on.
        r   zinvalid option string z&: must be at least two characters longr   r   r8   zinvalid short option string z/: must be of the form -x, (x any non-dash char)--zinvalid long option string z*: must start with --, followed by non-dashN)lenr|   r   rx   r   )r   r@   optr   r   r   r   1  s&    


zArgument._set_opt_stringsc                 C  s   g }| j r|dt| j  g7 }| jr8|dt| j g7 }|dt| j g7 }t| drj|dt| j g7 }t| dr|dt| j g7 }dd	|S )
Nz_short_opts: z_long_opts: zdest: ro   ztype: rp   z	default: zArgument({}), )	r   reprr   r2   hasattrro   rp   formatjoin)r   rF   r   r   r   r   N  s    

zArgument.__repr__N)	r   r   r   rz   r.   r]   rA   r   r   r   r   r   r   r/      s   r/   c                   @  sf   e Zd ZdZdddddddd	d
ddZddd	dddZddd	dddZdddd	dddZdS )r&   z,A group of options shown in its own section.r4   NFr   r   zParser | Noner    r!   )r5   r6   r%   r   r   c                C  s$   t | || _|| _g | _|| _d S r1   )r   r5   r6   r[   r%   )r   r5   r6   r%   r   r   r   r   r.   _  s
    zOptionGroup.__init__r   r?   c                 O  sJ   t |dd | jD }|r.td| dt||}| j|dd dS )aJ  Add an option to this group.

        If a shortened version of a long option is specified, it will
        be suppressed in the help. ``addoption('--twowords', '--two-words')``
        results in help showing ``--two-words`` only, but ``--twowords`` gets
        accepted **and** the automatic destination is in ``args.twowords``.

        :param opts:
            Option names, can be short or long options.
        :param attrs:
            Same attributes as the argparse library's :meth:`add_argument()
            <argparse.ArgumentParser.add_argument>` function accepts.
        c                 s  s    | ]}|  D ]
}|V  qqd S r1   )r]   )rM   r   r5   r   r   r   	<genexpr>{  s    
  z(OptionGroup.addoption.<locals>.<genexpr>zoption names z already addedF
shortupperN)setintersectionr[   
ValueErrorr/   _addoption_instance)r   r@   rA   conflictr0   r   r   r   rB   m  s    
zOptionGroup.addoptionc                 O  s   t ||}| j|dd d S )NTr   )r/   r   )r   r@   rA   r0   r   r   r   
_addoption  s    
zOptionGroup._addoptionr/   )r0   r   r   c                 C  sR   |s0|j D ]$}|d dkr
|d  r
tdq
| jrB| j| | j| d S )Nr   r   r8   zlowercase shortoptions reserved)r   islowerr   r%   r3   r[   rx   )r   r0   r   r   r   r   r   r     s    

zOptionGroup._addoption_instance)r4   N)F)r   r   r   rz   r.   rB   r   r   r   r   r   r   r&   \  s     r&   c                      sh   e Zd Zdddddd fddZd	d
dddZdddddddZejdk r`d	ddddZ  Z	S )rW   Nr   zdict[str, Any] | Noner   r!   )r%   r-   r   r   c                   s2   || _ t j||jdtddd |r(|ni | _d S )NF@)r   r"   add_helpformatter_classallow_abbrevfromfile_prefix_chars)_parsersuperr.   r*   DropShorterLongHelpFormatterr-   )r   r%   r-   r   	__class__r   r   r.     s    
zMyOptionParser.__init__r   r   )messager   c                 C  sD   | j  d| }t| jdr0| d| jj d}t|  | dS )z1Transform argparse error message into UsageError.z	: error: _config_source_hintz ()N)r   r   r   r   r   format_usage)r   r   r}   r   r   r   error  s    zMyOptionParser.errorzSequence[str] | NonerC   rD   rE   c           	      C  s   |  ||\}}|r|D ]d}|r|d dkrdd|g}t| j D ]\}}|d| d|  qL| d| qt|t	
| |S )z(Allow splitting of positional arguments.r   r   zunrecognized arguments: {} z  r   
)rl   r   r   sortedr-   rf   rx   r   rh   r_   extend)	r   rF   rG   parsedZunrecognizedarglineskvr   r   r   rT     s    zMyOptionParser.parse_args)   	   z5tuple[argparse.Action | None, str, str | None] | None)
arg_stringr   c           	      C  s  |sd S |d | j krd S || jkr8| j| }||d fS t|dkrHd S d|kr~|dd\}}|| jkr~| j| }|||fS | js|ds| |}t|dkrtd}ddd |D }| 	|||d	  nt|dkr|\}|S | j
|r| jsd S d
|krd S d |d fS )Nr   r8   =r   z4ambiguous option: %(option)s could match %(matches)sr   c                 s  s   | ]\}}}|V  qd S r1   r   )rM   r   r0   r   r   r   r     s     z1MyOptionParser._parse_optional.<locals>.<genexpr>)r0   matchesr   )prefix_chars_option_string_actionsr   r   r   
startswith_get_option_tuplesr   r   r   _negative_number_matchermatch_has_negative_number_optionals)	r   r   actionoption_stringexplicit_argoption_tuplesr}   r[   option_tupler   r   r   _parse_optional  s>    







zMyOptionParser._parse_optional)NN)NN)
r   r   r   r.   r   rT   sysversion_infor   __classcell__r   r   r   r   rW     s       
rW   c                      sF   e Zd ZdZdddd fddZddd	 fd
dZdd Z  ZS )r   a+  Shorten help for long options that differ only in extra hyphens.

    - Collapse **long** options that are the same except for extra hyphens.
    - Shortcut if there are only two options and one of them is a short one.
    - Cache result on the action object as this is called at least 2 times.
    r   r!   )rF   kwargsr   c                   s(   d|krt j |d< t j|| d S )Nwidth)_pytest_ioZget_terminal_widthr   r.   )r   rF   r   r   r   r   r.     s    z%DropShorterLongHelpFormatter.__init__zargparse.Actionr   )r   r   c                   sn  t  |}|r |d dkr |S t|dd }|r4|S |d}t|dkrtt|d dksjt|d dkrt||_|S g }i }|D ]v}t|dks|d dkrq|dstd	| d
||dd  }|dd}	|	|kst||	 t|k r|||	< q|D ]\}t|dks|d dkr&|	| |dd  |
|ddkr|	|ddd qd|}
|
|_|
S )Nr   r   _formatted_action_invocationr   r   r8   r   r   z&long optional argument without "--": []r4   r   )r   _format_action_invocationrh   r   r   r   r   r|   r   rx   r   r   )r   r   Zorgstrresr[   Zreturn_listZ
short_longr0   ZxxoptionZ	shortenedZformatted_action_invocationr   r   r   r     sD    
,

 


z6DropShorterLongHelpFormatter._format_action_invocationc                 C  s4   ddl }g }| D ]}||| | q|S )z}Wrap lines after splitting on original newlines.

        This allows to have explicit line breaks in the help text.
        r   N)textwrap
splitlinesr   wrapstrip)r   textr   r   r   liner   r   r   _split_lines  s
    z)DropShorterLongHelpFormatter._split_lines)r   r   r   rz   r.   r   r   r   r   r   r   r   r     s   &r   )#
__future__r   argparser   rJ   r   typingr   r   r   r   r   r	   r
   r   r   Z_pytest._ior   Z_pytest.config.exceptionsr   Z_pytest.deprecatedr   r_   r   rv   r   rw   	Exceptionr|   r/   r&   ArgumentParserrW   HelpFormatterr   r   r   r   r   <module>   s8    =]5X