a
    `f[                     @   s  d Z 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 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 eeZd
ZdZdZdZdZdZdd Zd#ddZdd Zej ej!G dd de"Z#dd Z$ej ej!G dd de"Z%dd Z&dd  Z'd!d" Z(dS )$a$  Certbot display.

This module (`certbot.display.util`) or its companion `certbot.display.ops`
should be used whenever:

- Displaying status information to the user on the terminal
- Collecting information from the user via prompts

Other messages can use the `logging` module. See `log.py`.

    N)List)errors)
interfaces)	constants)	completer)misc)osH   okZcancelhelpZesczO- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -c              	   C   s8   |   }g }|D ]}|tj|dddd qd|S )zFormat lines nicely to 80 chars.

    :param str msg: Original message

    :returns: Formatted message respecting newlines in message
    :rtype: str

    P   F)Zbreak_long_wordsZbreak_on_hyphens
)
splitlinesappendtextwrapZfilljoin)msglinesZfixed_lline r   6/usr/lib/python3/dist-packages/certbot/display/util.py_wrap_lines1   s    	
r        @c                 C   s8   | rt j|  t j  t|| }|s.t|dS )a  Get user input with a timeout.

    Behaves the same as six.moves.input, however, an error is raised if
    a user doesn't answer after timeout seconds. The default timeout
    value was chosen to place it just under 12 hours for users following
    our advice and running Certbot twice a day.

    :param str prompt: prompt to provide for input
    :param float timeout: maximum number of seconds to wait for input

    :returns: user response
    :rtype: str

    :raises errors.Error if no answer is given before the timeout

    r   )sysstdoutwriteflushr   Zreadline_with_timeoutEOFErrorrstrip)promptZtimeoutr   r   r   r   input_with_timeoutG   s    
r    c                 C   s    t jtjj| dddd dS )zMDisplay a basic status message.

    :param str msg: message to display

    F)pausedecoratewrapN)zopeZ	componentZ
getUtilityr   IDisplaynotification)r   r   r   r   notifye   s    r'   c                       s   e Zd ZdZ fddZdddZd d	d
Zd!ddZd"ddZd#ddZ	dd Z
dd Zd$ddZdd Zdd Zdd Z  ZS )%FileDisplayzFile-based display.c                    s$   t t|   || _|| _d| _d S )NF)superr(   __init__outfileforce_interactiveskipped_interaction)selfr+   r,   	__class__r   r   r*   v   s    zFileDisplay.__init__TFc                 C   sz   |rt |}td| | j|r&dndd |r4dnd jtjt|d | j	  |rv| 
|rltd n
td d	S )
a  Displays a notification and waits for user acceptance.

        :param str message: Message to display
        :param bool pause: Whether or not the program should pause for the
            user's confirmation
        :param bool wrap: Whether or not the application should wrap text
        :param bool force_interactive: True if it's safe to prompt the user
            because it won't cause any workflow regressions
        :param bool decorate: Whether to surround the message with a
            decorated frame

        Notifying user: %s{line}{frame}{line} {msg}{line}{frame}{line}r   framer   zPress Enter to Continuez!Not pausing for user confirmationN)r   loggerdebugr+   r   formatr   linesep
SIDE_FRAMEr   _can_interactr    )r.   messager!   r#   r,   r"   r   r   r   r&   |   s"    




zFileDisplay.notificationNc	                 K   sB   |  ||||rt|fS | || | t|\}
}|
|d fS )aC  Display a menu.

        .. todo:: This doesn't enable the help label/button (I wasn't sold on
           any interface I came up with for this). It would be a nice feature

        :param str message: title of menu
        :param choices: Menu lines, len must be > 0
        :type choices: list of tuples (tag, item) or
            list of descriptions (tags will be enumerated)
        :param default: default value to return (if one exists)
        :param str cli_flag: option used to set this value with the CLI
        :param bool force_interactive: True if it's safe to prompt the user
            because it won't cause any workflow regressions

        :returns: tuple of (`code`, `index`) where
            `code` - str display exit code
            `index` - int index of the user's selection

        :rtype: tuple

           )_return_defaultOK_print_menu_get_valid_int_anslen)r.   r>   choicesok_labelcancel_label
help_labeldefaultcli_flagr,   unused_kwargscode	selectionr   r   r   menu   s
    zFileDisplay.menuc                 K   sH   |  ||||rt|fS td| d }t|}|dv r@tdfS t|fS )a  Accept input from the user.

        :param str message: message to display to the user
        :param default: default value to return (if one exists)
        :param str cli_flag: option used to set this value with the CLI
        :param bool force_interactive: True if it's safe to prompt the user
            because it won't cause any workflow regressions

        :returns: tuple of (`code`, `input`) where
            `code` - str display exit code
            `input` - str of the user's input
        :rtype: tuple

        z%s (Enter 'c' to cancel): )cCz-1)r@   rA   r   r    CANCEL)r.   r>   rI   rJ   r,   rK   ansr   r   r   input   s    zFileDisplay.inputYesNoc           	      K   s   |  ||||r|S t|}| jdjtjttj |d | j  t	djt
|t
|d}||d  s||d  rdS ||d  s||d  rFdS qFdS )	a  Query the user with a yes/no question.

        Yes and No label must begin with different letters, and must contain at
        least one letter each.

        :param str message: question for the user
        :param str yes_label: Label of the "Yes" parameter
        :param str no_label: Label of the "No" parameter
        :param default: default value to return (if one exists)
        :param str cli_flag: option used to set this value with the CLI
        :param bool force_interactive: True if it's safe to prompt the user
            because it won't cause any workflow regressions

        :returns: True for "Yes", False for "No"
        :rtype: bool

        z{0}{frame}{msg}{0}{frame})r7   r   z{yes}/{no}: )ZyesZnor   TFN)r@   r   r+   r   r:   r   r;   r<   r   r    _parens_around_char
startswithlowerupper)	r.   r>   	yes_labelno_labelrI   rJ   r,   rK   rS   r   r   r   yesno   s&    

zFileDisplay.yesnoc                 K   s   |  ||||rt|fS | || | jddd\}}|tkr| shddd tdt|d D }t|}	| 	|	|}
|
r||
fS | j
dtj  | j
  q|g fS qd	S )
aC  Display a checklist.

        :param str message: Message to display to user
        :param list tags: `str` tags to select, len(tags) > 0
        :param default: default value to return (if one exists)
        :param str cli_flag: option used to set this value with the CLI
        :param bool force_interactive: True if it's safe to prompt the user
            because it won't cause any workflow regressions

        :returns: tuple of (`code`, `tags`) where
            `code` - str display exit code
            `tags` - list of selected tags
        :rtype: tuple

        zrSelect the appropriate numbers separated by commas and/or spaces, or leave input blank to select all options shownT)r,   rO   c                 s   s   | ]}t |V  qd S Nstr).0xr   r   r   	<genexpr>"      z(FileDisplay.checklist.<locals>.<genexpr>r?   z!** Error - Invalid selection **%sN)r@   rA   rB   rT   stripr   rangerD   separate_list_input_scrub_checklist_inputr+   r   r   r;   r   )r.   r>   tagsrI   rJ   r,   rK   rL   rS   indicesZselected_tagsr   r   r   	checklist  s$    
"zFileDisplay.checklistc                 C   sN   |  |rdS |du r<d|}|r2|d|7 }t|td|| dS )a  Should we return the default instead of prompting the user?

        :param str prompt: prompt for the user
        :param default: default answer to prompt
        :param str cli_flag: command line option for setting an answer
            to this question
        :param bool force_interactive: if interactivity is forced by the
            IDisplay call

        :returns: True if we should return the default without prompting
        :rtype: bool

        FNz-Unable to get an answer for the question:
{0}zA
You can provide an answer on the command line with the {0} flag.z-Falling back to default %s for the prompt:
%sT)r=   r:   r   Errorr8   r9   )r.   r   rI   rJ   r,   r   r   r   r   r@   -  s     


zFileDisplay._return_defaultc                 C   s@   | j s|stj r"| j r"dS | js<tdtj	 d| _dS )zCan we safely interact with the user?

        :param bool force_interactive: if interactivity is forced by the
            IDisplay call

        :returns: True if the display can interact with the user
        :rtype: bool

        TzSkipped user interaction because Certbot doesn't appear to be running in a terminal. You should probably include --non-interactive or %s on the command line.F)
r,   r   stdinisattyr+   r-   r8   Zwarningr   ZFORCE_INTERACTIVE_FLAG)r.   r,   r   r   r   r=   J  s    

zFileDisplay._can_interactc                 K   s<   t    | ||||W  d   S 1 s.0    Y  dS )a
  Display a directory selection screen.

        :param str message: prompt to give the user
        :param default: default value to return (if one exists)
        :param str cli_flag: option used to set this value with the CLI
        :param bool force_interactive: True if it's safe to prompt the user
            because it won't cause any workflow regressions

        :returns: tuple of the form (`code`, `string`) where
            `code` - display exit code
            `string` - input entered by the user

        N)r   Z	CompleterrT   )r.   r>   rI   rJ   r,   rK   r   r   r   directory_select`  s    
zFileDisplay.directory_selectc                    sn   zdd |D }W n t y(   g  Y S 0 tt|}|D ] }|dk sR|t kr:g   S q: fdd|D S )zValidate input and transform indices to appropriate tags.

        :param list indices: input
        :param list tags: Original tags of the checklist

        :returns: valid tags the user selected
        :rtype: :class:`list` of :class:`str`

        c                 S   s   g | ]}t |qS r   )intra   indexr   r   r   
<listcomp>~  rd   z6FileDisplay._scrub_checklist_input.<locals>.<listcomp>r?   c                    s   g | ]} |d   qS )r?   r   rq   ri   r   r   rs     rd   )
ValueErrorlistsetrD   )r.   rj   ri   rr   r   rt   r   rh   r  s    

z"FileDisplay._scrub_checklist_inputc                 C   s   |r t |d tr dd |D }| jdjtj|d | jttj  t|dD ]4\}}dj||d}| jt	| | jtj qT| jttj  | j
  d	S )
zPrint a menu on the screen.

        :param str message: title of menu
        :param choices: Menu lines
        :type choices: list of tuples (tag, item) or
            list of descriptions (tags will be enumerated)

        r   c                 S   s    g | ]}d |d |d f qS )z%s - %sr   r?   r   )ra   rP   r   r   r   rs     rd   z+FileDisplay._print_menu.<locals>.<listcomp>z{new}{msg}{new})newr   r?   z{num}: {desc})ZnumdescN)
isinstancetupler+   r   r:   r   r;   r<   	enumerater   r   )r.   r>   rE   iry   r   r   r   r   rB     s    
zFileDisplay._print_menuc                 C   s   d}|dkrdj |d}nd}|dk rt|}|dsB|drJtdfS z$t|}|dk sd||krld}tW q ty   | jd tj	 | j
  Y q0 qt|fS )	a5  Get a numerical selection.

        :param int max: The maximum entry (len of choices), must be positive

        :returns: tuple of the form (`code`, `selection`) where
            `code` - str display exit code ('ok' or cancel')
            `selection` - int user's selection
        :rtype: tuple

        r?   zMSelect the appropriate number [1-{max_}] then [enter] (press 'c' to cancel): )max_z@Press 1 [enter] to confirm the selection (press 'c' to cancel): rP   rQ   z{0}** Invalid input **{0})r:   r    rX   rR   rp   ru   r+   r   r   r;   r   rA   )r.   r   rM   Z	input_msgrS   r   r   r   rC     s*    
zFileDisplay._get_valid_int_ans)TTFT)NNNNNF)NNF)rU   rV   NNF)NNF)NNF)__name__
__module____qualname____doc__r*   r&   rN   rT   r]   rk   r@   r=   ro   rh   rB   rC   __classcell__r   r   r/   r   r(   q   s6      
"   
!  
  
*  
)  
r(   c                 C   s4   d | }|r|d |7 }|dus0|s0J |dS )aN  Verify that provided arguments is a valid IDisplay call.

    :param str prompt: prompt for the user
    :param default: default answer to prompt
    :param str cli_flag: command line option for setting an answer
        to this question
    :param bool force_interactive: if interactivity is forced by the
        IDisplay call

    z*Invalid IDisplay call for this prompt:
{0}z7
You can set an answer to this prompt with the {0} flagNr:   )r   rI   rJ   r,   r   r   r   r   assert_valid_call  s    
r   c                       sf   e Zd ZdZ fddZdddZdd	d
ZdddZdddZdddZ	dddZ
dddZ  ZS )NoninteractiveDisplayzEAn iDisplay implementation that never asks for interactive user inputc                    s   t t|   || _d S r^   )r)   r   r*   r+   )r.   r+   Zunused_argsrK   r/   r   r   r*     s    zNoninteractiveDisplay.__init__r3   c                 C   s<   d}||7 }|r|d| 7 }|r.|d |7 }t|dS )zBError out in case of an attempt to interact in noninteractive modez<Missing command line flag or config entry for this setting:
r   z&

(You can set this with the {0} flag)N)r:   r   ZMissingCommandlineFlag)r.   r>   rJ   Zextrar   r   r   r   _interaction_fail  s    z'NoninteractiveDisplay._interaction_failFTc                 K   sX   |rt |}td| | j|r&dndd |r4dnd jtjt|d | j	  dS )ae  Displays a notification without waiting for user acceptance.

        :param str message: Message to display to stdout
        :param bool pause: The NoninteractiveDisplay waits for no keyboard
        :param bool wrap: Whether or not the application should wrap text
        :param bool decorate: Whether to apply a decorated frame to the message

        r1   r2   r3   r4   r5   r6   N)
r   r8   r9   r+   r   r:   r   r;   r<   r   )r.   r>   r!   r#   r"   rK   r   r   r   r&     s    	

z"NoninteractiveDisplay.notificationNc           	      K   s&   |du r|  ||dt|  t|fS )a_  Avoid displaying a menu.

        :param str message: title of menu
        :param choices: Menu lines, len must be > 0
        :type choices: list of tuples (tag, item) or
            list of descriptions (tags will be enumerated)
        :param int default: the default choice
        :param dict kwargs: absorbs various irrelevant labelling arguments

        :returns: tuple of (`code`, `index`) where
            `code` - str display exit code
            `index` - int index of the user's selection
        :rtype: tuple
        :raises errors.MissingCommandlineFlag: if there was no default

        Nz	Choices: )r   reprrA   )	r.   r>   rE   rF   rG   rH   rI   rJ   rK   r   r   r   rN     s    zNoninteractiveDisplay.menuc                 K   s   |du r|  || t|fS )aK  Accept input from the user.

        :param str message: message to display to the user

        :returns: tuple of (`code`, `input`) where
            `code` - str display exit code
            `input` - str of the user's input
        :rtype: tuple
        :raises errors.MissingCommandlineFlag: if there was no default

        N)r   rA   r.   r>   rI   rJ   rK   r   r   r   rT      s    zNoninteractiveDisplay.inputc                 K   s   |du r|  || |S )a+  Decide Yes or No, without asking anybody

        :param str message: question for the user
        :param dict kwargs: absorbs yes_label, no_label

        :raises errors.MissingCommandlineFlag: if there was no default
        :returns: True for "Yes", False for "No"
        :rtype: bool

        N)r   )r.   r>   r[   r\   rI   rJ   rK   r   r   r   r]   0  s    zNoninteractiveDisplay.yesnoc                 K   s$   |du r|  ||d| t|fS )aj  Display a checklist.

        :param str message: Message to display to user
        :param list tags: `str` tags to select, len(tags) > 0
        :param dict kwargs: absorbs default_status arg

        :returns: tuple of (`code`, `tags`) where
            `code` - str display exit code
            `tags` - list of selected tags
        :rtype: tuple

        Nz? )r   r   rA   )r.   r>   ri   rI   rJ   rK   r   r   r   rk   @  s    zNoninteractiveDisplay.checklistc                 K   s   |  |||S )a  Simulate prompting the user for a directory.

        This function returns default if it is not ``None``, otherwise,
        an exception is raised explaining the problem. If cli_flag is
        not ``None``, the error message will include the flag that can
        be used to set this value with the CLI.

        :param str message: prompt to give the user
        :param default: default value to return (if one exists)
        :param str cli_flag: option used to set this value with the CLI

        :returns: tuple of the form (`code`, `string`) where
            `code` - int display exit code
            `string` - input entered by the user

        )rT   r   r   r   r   ro   R  s    z&NoninteractiveDisplay.directory_select)r3   )FTT)NNNNN)NN)NNNN)NN)NN)r   r   r   r   r*   r   r&   rN   rT   r]   rk   ro   r   r   r   r/   r   r     s"   


  

  
  
  r   c                 C   s   |  dd}dd | D S )zSeparate a comma or space separated list.

    :param str input_: input from the user

    :returns: strings
    :rtype: list

    ,rO   c                 S   s   g | ]}t |qS r   r_   )ra   stringr   r   r   rs   s  rd   z'separate_list_input.<locals>.<listcomp>)replacesplit)Zinput_Z	no_commasr   r   r   rg   g  s    	rg   c                 C   s   dj | d | dd dS )znPlace parens around first character of label.

    :param str label: Must contain at least one character

    z({first}){rest}r   r?   N)firstrestr   )Zlabelr   r   r   rW   v  s    rW   c                 C   sJ   | sdS t | }|dkr | d S |dkr2d| S d| d |d S dS )aM  Summarizes a list of domains in the format of:
        example.com.com and N more domains
    or if there is are only two domains:
        example.com and www.example.com
    or if there is only one domain:
        example.com

    :param list domains: `str` list of domains
    :returns: the domain list summary
    :rtype: str
    r3   r?   r      z and z{0} and {1} more domainsN)rD   r   r:   )Zdomainslr   r   r   summarize_domain_list  s    
r   )Nr   ))r   Zloggingr   r   Zzope.interfacer$   Zzope.componentZacme.magic_typingr   Zcertbotr   r   Zcertbot._internalr   Zcertbot._internal.displayr   Zcertbot.compatr   r   Z	getLoggerr   r8   ZWIDTHrA   rR   ZHELPZESCr<   r   r    r'   Z	interfaceZimplementerr%   objectr(   r   r   rg   rW   r   r   r   r   r   <module>   sB   

  ^ 	