
\\U                 @   si  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 e j e  Z d Z d	 Z d
 Z d Z d Z d d d Z d d   Z d d d d  Z e j j e
 j  Gd d   d e   Z d d   Z e j j e
 j  Gd d   d e   Z d d   Z  d d   Z! d S)zCertbot display.    N)compat)	constants)
interfaces)errors)	completerH   okZcancelhelpescz- '   -c          	   C   sU   |  j    } g  } x3 | D]+ } | j t j | d d d d d  q Wd j |  S)zFormat lines nicely to 80 chars.

    :param str msg: Original message

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

    P   Zbreak_long_wordsFZ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_lines%   s    	r   g     @c             C   sN   |  r# t  j j |   t  j j   t j | |   } | sA t  | j 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_timeout;   s    r    c                   s   e  Z d  Z d Z   f d d   Z d d d d d  Z d d d d d d d	 d
  Z d d d d d  Z d d d d d d d  Z d d d d d  Z	 d d   Z
 d d   Z d d d d d  Z d d   Z d d   Z d d   Z   S)FileDisplayzFile-based display.c                s2   t  t |   j   | |  _ | |  _ d |  _ d  S)NF)superr!   __init__outfileforce_interactiveskipped_interaction)selfr$   r%   )	__class__r   r   r#   _   s    		zFileDisplay.__init__TFc             C   s}   | r t  |  } |  j j d j d t j d t d |   |  j j   | ry |  j |  rl t	 d  n t
 j 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

        z+{line}{frame}{line}{msg}{line}{frame}{line}r   framer   zPress Enter to Continuez!Not pausing for user confirmationN)r   r$   r   formatoslinesep
SIDE_FRAMEr   _can_interactr    loggerdebug)r'   messagepausewrapr%   r   r   r   notificatione   s    		zFileDisplay.notificationNc	             K   s[   |  j  | | | |  r" t | f S|  j | |  |  j 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'   r1   choicesok_labelcancel_label
help_labeldefaultcli_flagr%   unused_kwargscode	selectionr   r   r   menu}   s
    
zFileDisplay.menuc             K   sr   |  j  | | | |  r" t | f St d |  d } t |  } | d k sZ | d k rd t d f St | f Sd 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-1N)r6   r7   r   r    CANCEL)r'   r1   r?   r@   r%   rA   ansr   r   r   input   s    

zFileDisplay.inputZYesZNoc       	      K   s  |  j  | | | |  r | St |  } |  j j d j t j d t t j d |  |  j j   x t	 d j d t
 |  d t
 |    } | j | d j    s | j | d j    r d S| j | d j    s | j | d j    rg d	 Sqg Wd
 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}r)   r   z{yes}/{no}: yesnor   TFN)r6   r   r$   r   r*   r+   r,   r-   r   r    _parens_around_char
startswithlowerupper)	r'   r1   	yes_labelno_labelr?   r@   r%   rA   rI   r   r   r   yesno   s      zFileDisplay.yesnoc             K   s
  |  j  | | | |  r" t | f Sx |  j | |  |  j d d d \ } } | t k r t | j    d k r d j d d   t d t |  d  D  } t |  }	 |  j	 |	 |  }
 |
 r | |
 f S|  j
 j d	 t j  |  j
 j   q% | g  f Sq% Wd
 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 shownr%   Tr   rE   c             s   s   |  ] } t  |  Vq d  S)N)str).0xr   r   r   	<genexpr>  s    z(FileDisplay.checklist.<locals>.<genexpr>r5   z!** Error - Invalid selection **%sN)r6   r7   r8   rJ   r:   stripr   rangeseparate_list_input_scrub_checklist_inputr$   r   r+   r,   r   )r'   r1   tagsr?   r@   r%   rA   rB   rI   indicesZselected_tagsr   r   r   	checklist   s"    
/
	zFileDisplay.checklistc             C   st   |  j  |  r d S| d k rY d j |  } | rG | d j |  7} t j |   n t j d | |  d Sd 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   Errorr/   r0   )r'   r   r?   r@   r%   r   r   r   r   r6     s    

zFileDisplay._return_defaultc             C   sZ   |  j  s- | s- t j j   r1 |  j j   r1 d S|  j sV t j 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&   r/   Zwarningr   ZFORCE_INTERACTIVE_FLAG)r'   r%   r   r   r   r.   .  s    
	
	zFileDisplay._can_interactc             K   s.   t  j    |  j | | | |  SWd QRXd 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	CompleterrJ   )r'   r1   r?   r@   r%   rA   r   r   r   directory_selectD  s    zFileDisplay.directory_selectc                s   y d d   | D } Wn t  k
 r/ g  SYn Xt t |   } x0 | D]( } | d k  sm | t    k rI g  SqI W  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 Sr   )int)rU   indexr   r   r   
<listcomp>c  s   	 z6FileDisplay._scrub_checklist_input.<locals>.<listcomp>r5   c                s   g  |  ] }   | d   q S)r5   r   )rU   rd   )r\   r   r   re   o  s   	 )
ValueErrorlistsetr:   )r'   r]   r\   rd   r   )r\   r   r[   V  s    	z"FileDisplay._scrub_checklist_inputc             C   s   | r, t  | d t  r, d d   | D } |  j j d j d t j d |   |  j j t t j  x^ t | d  D]M \ } } d j d	 | d
 |  } |  j j t	 |   |  j j t j  qx W|  j j t t j  |  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   r5   r   )rU   rF   r   r   r   re   |  s   	 z+FileDisplay._print_menu.<locals>.<listcomp>z{new}{msg}{new}newr   r5   z{num}: {desc}ZnumdescN)
isinstancetupler$   r   r*   r+   r,   r-   	enumerater   r   )r'   r1   r;   irj   r   r   r   r   r8   q  s    
	zFileDisplay._print_menuc             C   s   d } | d k r' d j  d |  } n d } x | d k  r t |  } | j d  sf | j d  rp t d	 f Sy4 t |  } | d k  s | | k r d
 } t  Wq0 t k
 r |  j j d j  t j	   |  j j
   Yq0 Xq0 Wt | 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

        r5   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): rF   rG   z{0}** Invalid input **{0}rp   rp   )r*   r    rN   rH   rc   rf   r$   r   r+   r,   r   r7   )r'   ro   rC   Z	input_msgrI   r   r   r   r9     s&    	

	zFileDisplay._get_valid_int_ans)__name__
__module____qualname____doc__r#   r4   rD   rJ   rS   r^   r6   r.   rb   r[   r8   r9   r   r   )r(   r   r!   Y   s(    	)*r!   c             C   sJ   d j  |   } | r( | d j  |  7} | d k	 sF | sF t |   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*   AssertionError)r   r?   r@   r%   r   r   r   r   assert_valid_call  s
    	
rv   c                   s   e  Z d  Z d Z   f d d   Z d d d  Z d d d	 d
  Z d d d d d d d  Z d d d d  Z d d d d d d  Z	 d d d d  Z
 d d d d  Z   S)NoninteractiveDisplayzEAn iDisplay implementation that never asks for interactive user inputc                s    t  t |   j   | |  _ d  S)N)r"   rw   r#   r$   )r'   r$   Zunused_argsrA   )r(   r   r   r#     s    zNoninteractiveDisplay.__init__ c             C   sP   d } | | 7} | r$ | d | 7} | r= | d j  |  7} t j |   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'   r1   r@   Zextrar   r   r   r   _interaction_fail  s    
z'NoninteractiveDisplay._interaction_failFTc             K   sN   | r t  |  } |  j j d j d t j d t d |   |  j j   d S)a  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

        z+{line}{frame}{line}{msg}{line}{frame}{line}r   r)   r   N)r   r$   r   r*   r+   r,   r-   r   )r'   r1   r2   r3   rA   r   r   r   r4     s    			z"NoninteractiveDisplay.notificationNc       	      K   s3   | d k r) |  j  | | 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: )ry   reprr7   )	r'   r1   r;   r<   r=   r>   r?   r@   rA   r   r   r   rD     s    zNoninteractiveDisplay.menuc             K   s-   | d k r |  j  | |  n
 t | f Sd 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)ry   r7   )r'   r1   r?   r@   rA   r   r   r   rJ     s    zNoninteractiveDisplay.inputc             K   s'   | d k r |  j  | |  n | Sd 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)ry   )r'   r1   rQ   rR   r?   r@   rA   r   r   r   rS     s    zNoninteractiveDisplay.yesnoc             K   s9   | d k r+ |  j  | | d j |   n
 t | f Sd 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? )ry   r   r7   )r'   r1   r\   r?   r@   rA   r   r   r   r^   "  s    zNoninteractiveDisplay.checklistc             K   s   |  j  | | |  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

        )rJ   )r'   r1   r?   r@   rA   r   r   r   rb   5  s    z&NoninteractiveDisplay.directory_select)rq   rr   rs   rt   r#   ry   r4   rD   rJ   rS   r^   rb   r   r   )r(   r   rw     s   
rw   c             C   s)   |  j  d d  } d d   | j   D S)zSeparate a comma or space separated list.

    :param str input_: input from the user

    :returns: strings
    :rtype: list

    ,rE   c             S   s   g  |  ] } t  |   q Sr   )rT   )rU   stringr   r   r   re   V  s   	 z'separate_list_input.<locals>.<listcomp>)replacesplit)Zinput_Z	no_commasr   r   r   rZ   J  s    	rZ   c             C   s$   d j  d |  d d |  d d   S)znPlace parens around first character of label.

    :param str label: Must contain at least one character

    z({first}){rest}firstr   restr5   N)r*   )Zlabelr   r   r   rM   Y  s    rM   )"rt   Zloggingr+   r   r   Zzope.interfacezopeZcertbotr   r   r   r   Zcertbot.displayr   Z	getLoggerrq   r/   ZWIDTHr7   rH   ZHELPZESCr-   r   r    Z	interfaceZimplementerZIDisplayobjectr!   rv   rw   rZ   rM   r   r   r   r   <module>   s6    Z