1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
"""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`.
"""
from typing import List
from typing import Optional
from typing import Tuple
from typing import Union
from certbot._internal.display import obj
# These constants are defined this way to make them easier to document with
# Sphinx and to not couple our public docstrings to our internal ones.
OK = obj.OK
"""Display exit code indicating user acceptance."""
CANCEL = obj.CANCEL
"""Display exit code for a user canceling the display."""
WIDTH = 72
def notify(msg: str) -> None:
"""Display a basic status message.
:param str msg: message to display
"""
obj.get_display().notification(msg, pause=False, decorate=False, wrap=False)
def notification(message: str, pause: bool = True, wrap: bool = True,
force_interactive: bool = False, decorate: bool = True) -> None:
"""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
"""
obj.get_display().notification(message, pause=pause, wrap=wrap,
force_interactive=force_interactive, decorate=decorate)
def menu(message: str, choices: Union[List[str], List[Tuple[str, str]]],
default: Optional[int] = None, cli_flag: Optional[str] = None,
force_interactive: bool = False) -> Tuple[str, int]:
"""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 interaction is not possible
: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 obj.get_display().menu(message, choices, default=default, cli_flag=cli_flag,
force_interactive=force_interactive)
def input_text(message: str, default: Optional[str] = None, cli_flag: Optional[str] = None,
force_interactive: bool = False) -> Tuple[str, str]:
"""Accept input from the user.
:param str message: message to display to the user
:param default: default value to return, if interaction is not possible
: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
"""
return obj.get_display().input(message, default=default, cli_flag=cli_flag,
force_interactive=force_interactive)
def yesno(message: str, yes_label: str = "Yes", no_label: str = "No",
default: Optional[bool] = None, cli_flag: Optional[str] = None,
force_interactive: bool = False) -> bool:
"""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 interaction is not possible
: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
"""
return obj.get_display().yesno(message, yes_label=yes_label, no_label=no_label, default=default,
cli_flag=cli_flag, force_interactive=force_interactive)
def checklist(message: str, tags: List[str], default: Optional[List[str]] = None,
cli_flag: Optional[str] = None,
force_interactive: bool = False) -> Tuple[str, List[str]]:
"""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 interaction is not possible
: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
"""
return obj.get_display().checklist(message, tags, default=default, cli_flag=cli_flag,
force_interactive=force_interactive)
def directory_select(message: str, default: Optional[str] = None, cli_flag: Optional[str] = None,
force_interactive: bool = False) -> Tuple[str, str]:
"""Display a directory selection screen.
:param str message: prompt to give the user
:param default: default value to return, if interaction is not possible
: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
"""
return obj.get_display().directory_select(message, default=default, cli_flag=cli_flag,
force_interactive=force_interactive)
def assert_valid_call(prompt: str, default: str, cli_flag: str, force_interactive: bool) -> None:
"""Verify that provided arguments is a valid display 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
"""
msg = "Invalid display call for this prompt:\n{0}".format(prompt)
if cli_flag:
msg += ("\nYou can set an answer to "
"this prompt with the {0} flag".format(cli_flag))
assert default is not None or force_interactive, msg
|