We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add deprecation warnings for legacy certbot.display.util code
As a followup from https://github.com/certbot/certbot/pull/8967, I think we should generate deprecation warnings using an approach like https://github.com/certbot/certbot/pull/6859/files#diff-e5eaf744409c293203b898ba9896da75689fd04ff5f1566c035940a5b195c257 for any code in `certbot.display.util` that is unused and/or we don't want to be part of our public API.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `certbot/certbot/display/util.py`
Content:
```
1 """Certbot display.
2 
3 This module (`certbot.display.util`) or its companion `certbot.display.ops`
4 should be used whenever:
5 
6 - Displaying status information to the user on the terminal
7 - Collecting information from the user via prompts
8 
9 Other messages can use the `logging` module. See `log.py`.
10 
11 """
12 from typing import List
13 from typing import Optional
14 from typing import Tuple
15 from typing import Union
16 
17 
18 # These specific imports from certbot._internal.display.obj and
19 # certbot._internal.display.util are done to not break the public API of this
20 # module.
21 from certbot._internal.display.obj import FileDisplay  # pylint: disable=unused-import
22 from certbot._internal.display.obj import NoninteractiveDisplay  # pylint: disable=unused-import
23 from certbot._internal.display.obj import SIDE_FRAME  # pylint: disable=unused-import
24 from certbot._internal.display.util import input_with_timeout  # pylint: disable=unused-import
25 from certbot._internal.display.util import separate_list_input  # pylint: disable=unused-import
26 from certbot._internal.display.util import summarize_domain_list  # pylint: disable=unused-import
27 from certbot._internal.display import obj
28 
29 
30 # These constants are defined this way to make them easier to document with
31 # Sphinx and to not couple our public docstrings to our internal ones.
32 OK = obj.OK
33 """Display exit code indicating user acceptance."""
34 
35 CANCEL = obj.CANCEL
36 """Display exit code for a user canceling the display."""
37 
38 # These constants are unused and should be removed in a major release of
39 # Certbot.
40 WIDTH = 72
41 
42 HELP = "help"
43 """Display exit code when for when the user requests more help. (UNUSED)"""
44 
45 ESC = "esc"
46 """Display exit code when the user hits Escape (UNUSED)"""
47 
48 
49 def notify(msg: str) -> None:
50     """Display a basic status message.
51 
52     :param str msg: message to display
53 
54     """
55     obj.get_display().notification(msg, pause=False, decorate=False, wrap=False)
56 
57 
58 def notification(message: str, pause: bool = True, wrap: bool = True,
59                  force_interactive: bool = False, decorate: bool = True) -> None:
60     """Displays a notification and waits for user acceptance.
61 
62     :param str message: Message to display
63     :param bool pause: Whether or not the program should pause for the
64         user's confirmation
65     :param bool wrap: Whether or not the application should wrap text
66     :param bool force_interactive: True if it's safe to prompt the user
67         because it won't cause any workflow regressions
68     :param bool decorate: Whether to surround the message with a
69         decorated frame
70 
71     """
72     obj.get_display().notification(message, pause=pause, wrap=wrap,
73                                    force_interactive=force_interactive, decorate=decorate)
74 
75 
76 def menu(message: str, choices: Union[List[str], Tuple[str, str]],
77          default: Optional[int] = None, cli_flag: Optional[str] = None,
78          force_interactive: bool = False) -> Tuple[str, int]:
79     """Display a menu.
80 
81     .. todo:: This doesn't enable the help label/button (I wasn't sold on
82         any interface I came up with for this). It would be a nice feature.
83 
84     :param str message: title of menu
85     :param choices: Menu lines, len must be > 0
86     :type choices: list of tuples (tag, item) or
87         list of descriptions (tags will be enumerated)
88     :param default: default value to return (if one exists)
89     :param str cli_flag: option used to set this value with the CLI
90     :param bool force_interactive: True if it's safe to prompt the user
91         because it won't cause any workflow regressions
92 
93     :returns: tuple of (`code`, `index`) where
94         `code` - str display exit code
95         `index` - int index of the user's selection
96 
97     :rtype: tuple
98 
99     """
100     return obj.get_display().menu(message, choices, default=default, cli_flag=cli_flag,
101                                   force_interactive=force_interactive)
102 
103 
104 def input_text(message: str, default: Optional[str] = None, cli_flag: Optional[str] = None,
105                force_interactive: bool = False) -> Tuple[str, str]:
106     """Accept input from the user.
107 
108     :param str message: message to display to the user
109     :param default: default value to return (if one exists)
110     :param str cli_flag: option used to set this value with the CLI
111     :param bool force_interactive: True if it's safe to prompt the user
112         because it won't cause any workflow regressions
113 
114     :returns: tuple of (`code`, `input`) where
115         `code` - str display exit code
116         `input` - str of the user's input
117     :rtype: tuple
118 
119     """
120     return obj.get_display().input(message, default=default, cli_flag=cli_flag,
121                                    force_interactive=force_interactive)
122 
123 
124 def yesno(message: str, yes_label: str = "Yes", no_label: str = "No",
125           default: Optional[bool] = None, cli_flag: Optional[str] = None,
126           force_interactive: bool = False) -> bool:
127     """Query the user with a yes/no question.
128 
129     Yes and No label must begin with different letters, and must contain at
130     least one letter each.
131 
132     :param str message: question for the user
133     :param str yes_label: Label of the "Yes" parameter
134     :param str no_label: Label of the "No" parameter
135     :param default: default value to return (if one exists)
136     :param str cli_flag: option used to set this value with the CLI
137     :param bool force_interactive: True if it's safe to prompt the user
138         because it won't cause any workflow regressions
139 
140     :returns: True for "Yes", False for "No"
141     :rtype: bool
142 
143     """
144     return obj.get_display().yesno(message, yes_label=yes_label, no_label=no_label, default=default,
145                                    cli_flag=cli_flag, force_interactive=force_interactive)
146 
147 
148 def checklist(message: str, tags: List[str], default: Optional[str] = None,
149               cli_flag: Optional[str] = None,
150               force_interactive: bool = False) -> Tuple[str, List[str]]:
151     """Display a checklist.
152 
153     :param str message: Message to display to user
154     :param list tags: `str` tags to select, len(tags) > 0
155     :param default: default value to return (if one exists)
156     :param str cli_flag: option used to set this value with the CLI
157     :param bool force_interactive: True if it's safe to prompt the user
158         because it won't cause any workflow regressions
159 
160     :returns: tuple of (`code`, `tags`) where
161         `code` - str display exit code
162         `tags` - list of selected tags
163     :rtype: tuple
164 
165     """
166     return obj.get_display().checklist(message, tags, default=default, cli_flag=cli_flag,
167                                        force_interactive=force_interactive)
168 
169 
170 def directory_select(message: str, default: Optional[str] = None, cli_flag: Optional[str] = None,
171                      force_interactive: bool = False) -> Tuple[int, str]:
172     """Display a directory selection screen.
173 
174     :param str message: prompt to give the user
175     :param default: default value to return (if one exists)
176     :param str cli_flag: option used to set this value with the CLI
177     :param bool force_interactive: True if it's safe to prompt the user
178         because it won't cause any workflow regressions
179 
180     :returns: tuple of the form (`code`, `string`) where
181         `code` - display exit code
182         `string` - input entered by the user
183 
184     """
185     return obj.get_display().directory_select(message, default=default, cli_flag=cli_flag,
186                                               force_interactive=force_interactive)
187 
188 
189 def assert_valid_call(prompt, default, cli_flag, force_interactive):
190     """Verify that provided arguments is a valid IDisplay call.
191 
192     :param str prompt: prompt for the user
193     :param default: default answer to prompt
194     :param str cli_flag: command line option for setting an answer
195         to this question
196     :param bool force_interactive: if interactivity is forced by the
197         IDisplay call
198 
199     """
200     msg = "Invalid IDisplay call for this prompt:\n{0}".format(prompt)
201     if cli_flag:
202         msg += ("\nYou can set an answer to "
203                 "this prompt with the {0} flag".format(cli_flag))
204     assert default is not None or force_interactive, msg
205
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/certbot/certbot/display/util.py b/certbot/certbot/display/util.py
--- a/certbot/certbot/display/util.py
+++ b/certbot/certbot/display/util.py
@@ -9,10 +9,14 @@
 Other messages can use the `logging` module. See `log.py`.
 
 """
+import sys
+from types import ModuleType
+from typing import cast
 from typing import List
 from typing import Optional
 from typing import Tuple
 from typing import Union
+import warnings
 
 
 # These specific imports from certbot._internal.display.obj and
@@ -202,3 +206,36 @@
         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
+
+
+# This class takes a similar approach to the cryptography project to deprecate attributes
+# in public modules. See the _ModuleWithDeprecation class here:
+# https://github.com/pyca/cryptography/blob/91105952739442a74582d3e62b3d2111365b0dc7/src/cryptography/utils.py#L129
+class _DisplayUtilDeprecationModule:
+    """
+    Internal class delegating to a module, and displaying warnings when attributes
+    related to deprecated attributes in the certbot.display.util module.
+    """
+    def __init__(self, module):
+        self.__dict__['_module'] = module
+
+    def __getattr__(self, attr):
+        if attr in ('FileDisplay', 'NoninteractiveDisplay', 'SIDE_FRAME', 'input_with_timeout',
+                    'separate_list_input', 'summarize_domain_list', 'WIDTH', 'HELP', 'ESC'):
+            warnings.warn('{0} attribute in certbot.display.util module is deprecated '
+                          'and will be removed soon.'.format(attr),
+                          DeprecationWarning, stacklevel=2)
+        return getattr(self._module, attr)
+
+    def __setattr__(self, attr, value):  # pragma: no cover
+        setattr(self._module, attr, value)
+
+    def __delattr__(self, attr):  # pragma: no cover
+        delattr(self._module, attr)
+
+    def __dir__(self):  # pragma: no cover
+        return ['_module'] + dir(self._module)
+
+
+# Patching ourselves to warn about deprecation and planned removal of some elements in the module.
+sys.modules[__name__] = cast(ModuleType, _DisplayUtilDeprecationModule(sys.modules[__name__]))

{"golden_diff": "diff --git a/certbot/certbot/display/util.py b/certbot/certbot/display/util.py\n--- a/certbot/certbot/display/util.py\n+++ b/certbot/certbot/display/util.py\n@@ -9,10 +9,14 @@\n Other messages can use the `logging` module. See `log.py`.\n \n \"\"\"\n+import sys\n+from types import ModuleType\n+from typing import cast\n from typing import List\n from typing import Optional\n from typing import Tuple\n from typing import Union\n+import warnings\n \n \n # These specific imports from certbot._internal.display.obj and\n@@ -202,3 +206,36 @@\n         msg += (\"\\nYou can set an answer to \"\n                 \"this prompt with the {0} flag\".format(cli_flag))\n     assert default is not None or force_interactive, msg\n+\n+\n+# This class takes a similar approach to the cryptography project to deprecate attributes\n+# in public modules. See the _ModuleWithDeprecation class here:\n+# https://github.com/pyca/cryptography/blob/91105952739442a74582d3e62b3d2111365b0dc7/src/cryptography/utils.py#L129\n+class _DisplayUtilDeprecationModule:\n+    \"\"\"\n+    Internal class delegating to a module, and displaying warnings when attributes\n+    related to deprecated attributes in the certbot.display.util module.\n+    \"\"\"\n+    def __init__(self, module):\n+        self.__dict__['_module'] = module\n+\n+    def __getattr__(self, attr):\n+        if attr in ('FileDisplay', 'NoninteractiveDisplay', 'SIDE_FRAME', 'input_with_timeout',\n+                    'separate_list_input', 'summarize_domain_list', 'WIDTH', 'HELP', 'ESC'):\n+            warnings.warn('{0} attribute in certbot.display.util module is deprecated '\n+                          'and will be removed soon.'.format(attr),\n+                          DeprecationWarning, stacklevel=2)\n+        return getattr(self._module, attr)\n+\n+    def __setattr__(self, attr, value):  # pragma: no cover\n+        setattr(self._module, attr, value)\n+\n+    def __delattr__(self, attr):  # pragma: no cover\n+        delattr(self._module, attr)\n+\n+    def __dir__(self):  # pragma: no cover\n+        return ['_module'] + dir(self._module)\n+\n+\n+# Patching ourselves to warn about deprecation and planned removal of some elements in the module.\n+sys.modules[__name__] = cast(ModuleType, _DisplayUtilDeprecationModule(sys.modules[__name__]))\n", "issue": "Add deprecation warnings for legacy certbot.display.util code\nAs a followup from https://github.com/certbot/certbot/pull/8967, I think we should generate deprecation warnings using an approach like https://github.com/certbot/certbot/pull/6859/files#diff-e5eaf744409c293203b898ba9896da75689fd04ff5f1566c035940a5b195c257 for any code in `certbot.display.util` that is unused and/or we don't want to be part of our public API.\n", "before_files": [{"content": "\"\"\"Certbot display.\n\nThis module (`certbot.display.util`) or its companion `certbot.display.ops`\nshould be used whenever:\n\n- Displaying status information to the user on the terminal\n- Collecting information from the user via prompts\n\nOther messages can use the `logging` module. See `log.py`.\n\n\"\"\"\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\nfrom typing import Union\n\n\n# These specific imports from certbot._internal.display.obj and\n# certbot._internal.display.util are done to not break the public API of this\n# module.\nfrom certbot._internal.display.obj import FileDisplay  # pylint: disable=unused-import\nfrom certbot._internal.display.obj import NoninteractiveDisplay  # pylint: disable=unused-import\nfrom certbot._internal.display.obj import SIDE_FRAME  # pylint: disable=unused-import\nfrom certbot._internal.display.util import input_with_timeout  # pylint: disable=unused-import\nfrom certbot._internal.display.util import separate_list_input  # pylint: disable=unused-import\nfrom certbot._internal.display.util import summarize_domain_list  # pylint: disable=unused-import\nfrom certbot._internal.display import obj\n\n\n# These constants are defined this way to make them easier to document with\n# Sphinx and to not couple our public docstrings to our internal ones.\nOK = obj.OK\n\"\"\"Display exit code indicating user acceptance.\"\"\"\n\nCANCEL = obj.CANCEL\n\"\"\"Display exit code for a user canceling the display.\"\"\"\n\n# These constants are unused and should be removed in a major release of\n# Certbot.\nWIDTH = 72\n\nHELP = \"help\"\n\"\"\"Display exit code when for when the user requests more help. (UNUSED)\"\"\"\n\nESC = \"esc\"\n\"\"\"Display exit code when the user hits Escape (UNUSED)\"\"\"\n\n\ndef notify(msg: str) -> None:\n    \"\"\"Display a basic status message.\n\n    :param str msg: message to display\n\n    \"\"\"\n    obj.get_display().notification(msg, pause=False, decorate=False, wrap=False)\n\n\ndef notification(message: str, pause: bool = True, wrap: bool = True,\n                 force_interactive: bool = False, decorate: bool = True) -> None:\n    \"\"\"Displays a notification and waits for user acceptance.\n\n    :param str message: Message to display\n    :param bool pause: Whether or not the program should pause for the\n        user's confirmation\n    :param bool wrap: Whether or not the application should wrap text\n    :param bool force_interactive: True if it's safe to prompt the user\n        because it won't cause any workflow regressions\n    :param bool decorate: Whether to surround the message with a\n        decorated frame\n\n    \"\"\"\n    obj.get_display().notification(message, pause=pause, wrap=wrap,\n                                   force_interactive=force_interactive, decorate=decorate)\n\n\ndef menu(message: str, choices: Union[List[str], Tuple[str, str]],\n         default: Optional[int] = None, cli_flag: Optional[str] = None,\n         force_interactive: bool = False) -> Tuple[str, int]:\n    \"\"\"Display a menu.\n\n    .. todo:: This doesn't enable the help label/button (I wasn't sold on\n        any interface I came up with for this). It would be a nice feature.\n\n    :param str message: title of menu\n    :param choices: Menu lines, len must be > 0\n    :type choices: list of tuples (tag, item) or\n        list of descriptions (tags will be enumerated)\n    :param default: default value to return (if one exists)\n    :param str cli_flag: option used to set this value with the CLI\n    :param bool force_interactive: True if it's safe to prompt the user\n        because it won't cause any workflow regressions\n\n    :returns: tuple of (`code`, `index`) where\n        `code` - str display exit code\n        `index` - int index of the user's selection\n\n    :rtype: tuple\n\n    \"\"\"\n    return obj.get_display().menu(message, choices, default=default, cli_flag=cli_flag,\n                                  force_interactive=force_interactive)\n\n\ndef input_text(message: str, default: Optional[str] = None, cli_flag: Optional[str] = None,\n               force_interactive: bool = False) -> Tuple[str, str]:\n    \"\"\"Accept input from the user.\n\n    :param str message: message to display to the user\n    :param default: default value to return (if one exists)\n    :param str cli_flag: option used to set this value with the CLI\n    :param bool force_interactive: True if it's safe to prompt the user\n        because it won't cause any workflow regressions\n\n    :returns: tuple of (`code`, `input`) where\n        `code` - str display exit code\n        `input` - str of the user's input\n    :rtype: tuple\n\n    \"\"\"\n    return obj.get_display().input(message, default=default, cli_flag=cli_flag,\n                                   force_interactive=force_interactive)\n\n\ndef yesno(message: str, yes_label: str = \"Yes\", no_label: str = \"No\",\n          default: Optional[bool] = None, cli_flag: Optional[str] = None,\n          force_interactive: bool = False) -> bool:\n    \"\"\"Query the user with a yes/no question.\n\n    Yes and No label must begin with different letters, and must contain at\n    least one letter each.\n\n    :param str message: question for the user\n    :param str yes_label: Label of the \"Yes\" parameter\n    :param str no_label: Label of the \"No\" parameter\n    :param default: default value to return (if one exists)\n    :param str cli_flag: option used to set this value with the CLI\n    :param bool force_interactive: True if it's safe to prompt the user\n        because it won't cause any workflow regressions\n\n    :returns: True for \"Yes\", False for \"No\"\n    :rtype: bool\n\n    \"\"\"\n    return obj.get_display().yesno(message, yes_label=yes_label, no_label=no_label, default=default,\n                                   cli_flag=cli_flag, force_interactive=force_interactive)\n\n\ndef checklist(message: str, tags: List[str], default: Optional[str] = None,\n              cli_flag: Optional[str] = None,\n              force_interactive: bool = False) -> Tuple[str, List[str]]:\n    \"\"\"Display a checklist.\n\n    :param str message: Message to display to user\n    :param list tags: `str` tags to select, len(tags) > 0\n    :param default: default value to return (if one exists)\n    :param str cli_flag: option used to set this value with the CLI\n    :param bool force_interactive: True if it's safe to prompt the user\n        because it won't cause any workflow regressions\n\n    :returns: tuple of (`code`, `tags`) where\n        `code` - str display exit code\n        `tags` - list of selected tags\n    :rtype: tuple\n\n    \"\"\"\n    return obj.get_display().checklist(message, tags, default=default, cli_flag=cli_flag,\n                                       force_interactive=force_interactive)\n\n\ndef directory_select(message: str, default: Optional[str] = None, cli_flag: Optional[str] = None,\n                     force_interactive: bool = False) -> Tuple[int, str]:\n    \"\"\"Display a directory selection screen.\n\n    :param str message: prompt to give the user\n    :param default: default value to return (if one exists)\n    :param str cli_flag: option used to set this value with the CLI\n    :param bool force_interactive: True if it's safe to prompt the user\n        because it won't cause any workflow regressions\n\n    :returns: tuple of the form (`code`, `string`) where\n        `code` - display exit code\n        `string` - input entered by the user\n\n    \"\"\"\n    return obj.get_display().directory_select(message, default=default, cli_flag=cli_flag,\n                                              force_interactive=force_interactive)\n\n\ndef assert_valid_call(prompt, default, cli_flag, force_interactive):\n    \"\"\"Verify that provided arguments is a valid IDisplay call.\n\n    :param str prompt: prompt for the user\n    :param default: default answer to prompt\n    :param str cli_flag: command line option for setting an answer\n        to this question\n    :param bool force_interactive: if interactivity is forced by the\n        IDisplay call\n\n    \"\"\"\n    msg = \"Invalid IDisplay call for this prompt:\\n{0}\".format(prompt)\n    if cli_flag:\n        msg += (\"\\nYou can set an answer to \"\n                \"this prompt with the {0} flag\".format(cli_flag))\n    assert default is not None or force_interactive, msg\n", "path": "certbot/certbot/display/util.py"}], "after_files": [{"content": "\"\"\"Certbot display.\n\nThis module (`certbot.display.util`) or its companion `certbot.display.ops`\nshould be used whenever:\n\n- Displaying status information to the user on the terminal\n- Collecting information from the user via prompts\n\nOther messages can use the `logging` module. See `log.py`.\n\n\"\"\"\nimport sys\nfrom types import ModuleType\nfrom typing import cast\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\nfrom typing import Union\nimport warnings\n\n\n# These specific imports from certbot._internal.display.obj and\n# certbot._internal.display.util are done to not break the public API of this\n# module.\nfrom certbot._internal.display.obj import FileDisplay  # pylint: disable=unused-import\nfrom certbot._internal.display.obj import NoninteractiveDisplay  # pylint: disable=unused-import\nfrom certbot._internal.display.obj import SIDE_FRAME  # pylint: disable=unused-import\nfrom certbot._internal.display.util import input_with_timeout  # pylint: disable=unused-import\nfrom certbot._internal.display.util import separate_list_input  # pylint: disable=unused-import\nfrom certbot._internal.display.util import summarize_domain_list  # pylint: disable=unused-import\nfrom certbot._internal.display import obj\n\n\n# These constants are defined this way to make them easier to document with\n# Sphinx and to not couple our public docstrings to our internal ones.\nOK = obj.OK\n\"\"\"Display exit code indicating user acceptance.\"\"\"\n\nCANCEL = obj.CANCEL\n\"\"\"Display exit code for a user canceling the display.\"\"\"\n\n# These constants are unused and should be removed in a major release of\n# Certbot.\nWIDTH = 72\n\nHELP = \"help\"\n\"\"\"Display exit code when for when the user requests more help. (UNUSED)\"\"\"\n\nESC = \"esc\"\n\"\"\"Display exit code when the user hits Escape (UNUSED)\"\"\"\n\n\ndef notify(msg: str) -> None:\n    \"\"\"Display a basic status message.\n\n    :param str msg: message to display\n\n    \"\"\"\n    obj.get_display().notification(msg, pause=False, decorate=False, wrap=False)\n\n\ndef notification(message: str, pause: bool = True, wrap: bool = True,\n                 force_interactive: bool = False, decorate: bool = True) -> None:\n    \"\"\"Displays a notification and waits for user acceptance.\n\n    :param str message: Message to display\n    :param bool pause: Whether or not the program should pause for the\n        user's confirmation\n    :param bool wrap: Whether or not the application should wrap text\n    :param bool force_interactive: True if it's safe to prompt the user\n        because it won't cause any workflow regressions\n    :param bool decorate: Whether to surround the message with a\n        decorated frame\n\n    \"\"\"\n    obj.get_display().notification(message, pause=pause, wrap=wrap,\n                                   force_interactive=force_interactive, decorate=decorate)\n\n\ndef menu(message: str, choices: Union[List[str], Tuple[str, str]],\n         default: Optional[int] = None, cli_flag: Optional[str] = None,\n         force_interactive: bool = False) -> Tuple[str, int]:\n    \"\"\"Display a menu.\n\n    .. todo:: This doesn't enable the help label/button (I wasn't sold on\n        any interface I came up with for this). It would be a nice feature.\n\n    :param str message: title of menu\n    :param choices: Menu lines, len must be > 0\n    :type choices: list of tuples (tag, item) or\n        list of descriptions (tags will be enumerated)\n    :param default: default value to return (if one exists)\n    :param str cli_flag: option used to set this value with the CLI\n    :param bool force_interactive: True if it's safe to prompt the user\n        because it won't cause any workflow regressions\n\n    :returns: tuple of (`code`, `index`) where\n        `code` - str display exit code\n        `index` - int index of the user's selection\n\n    :rtype: tuple\n\n    \"\"\"\n    return obj.get_display().menu(message, choices, default=default, cli_flag=cli_flag,\n                                  force_interactive=force_interactive)\n\n\ndef input_text(message: str, default: Optional[str] = None, cli_flag: Optional[str] = None,\n               force_interactive: bool = False) -> Tuple[str, str]:\n    \"\"\"Accept input from the user.\n\n    :param str message: message to display to the user\n    :param default: default value to return (if one exists)\n    :param str cli_flag: option used to set this value with the CLI\n    :param bool force_interactive: True if it's safe to prompt the user\n        because it won't cause any workflow regressions\n\n    :returns: tuple of (`code`, `input`) where\n        `code` - str display exit code\n        `input` - str of the user's input\n    :rtype: tuple\n\n    \"\"\"\n    return obj.get_display().input(message, default=default, cli_flag=cli_flag,\n                                   force_interactive=force_interactive)\n\n\ndef yesno(message: str, yes_label: str = \"Yes\", no_label: str = \"No\",\n          default: Optional[bool] = None, cli_flag: Optional[str] = None,\n          force_interactive: bool = False) -> bool:\n    \"\"\"Query the user with a yes/no question.\n\n    Yes and No label must begin with different letters, and must contain at\n    least one letter each.\n\n    :param str message: question for the user\n    :param str yes_label: Label of the \"Yes\" parameter\n    :param str no_label: Label of the \"No\" parameter\n    :param default: default value to return (if one exists)\n    :param str cli_flag: option used to set this value with the CLI\n    :param bool force_interactive: True if it's safe to prompt the user\n        because it won't cause any workflow regressions\n\n    :returns: True for \"Yes\", False for \"No\"\n    :rtype: bool\n\n    \"\"\"\n    return obj.get_display().yesno(message, yes_label=yes_label, no_label=no_label, default=default,\n                                   cli_flag=cli_flag, force_interactive=force_interactive)\n\n\ndef checklist(message: str, tags: List[str], default: Optional[str] = None,\n              cli_flag: Optional[str] = None,\n              force_interactive: bool = False) -> Tuple[str, List[str]]:\n    \"\"\"Display a checklist.\n\n    :param str message: Message to display to user\n    :param list tags: `str` tags to select, len(tags) > 0\n    :param default: default value to return (if one exists)\n    :param str cli_flag: option used to set this value with the CLI\n    :param bool force_interactive: True if it's safe to prompt the user\n        because it won't cause any workflow regressions\n\n    :returns: tuple of (`code`, `tags`) where\n        `code` - str display exit code\n        `tags` - list of selected tags\n    :rtype: tuple\n\n    \"\"\"\n    return obj.get_display().checklist(message, tags, default=default, cli_flag=cli_flag,\n                                       force_interactive=force_interactive)\n\n\ndef directory_select(message: str, default: Optional[str] = None, cli_flag: Optional[str] = None,\n                     force_interactive: bool = False) -> Tuple[int, str]:\n    \"\"\"Display a directory selection screen.\n\n    :param str message: prompt to give the user\n    :param default: default value to return (if one exists)\n    :param str cli_flag: option used to set this value with the CLI\n    :param bool force_interactive: True if it's safe to prompt the user\n        because it won't cause any workflow regressions\n\n    :returns: tuple of the form (`code`, `string`) where\n        `code` - display exit code\n        `string` - input entered by the user\n\n    \"\"\"\n    return obj.get_display().directory_select(message, default=default, cli_flag=cli_flag,\n                                              force_interactive=force_interactive)\n\n\ndef assert_valid_call(prompt, default, cli_flag, force_interactive):\n    \"\"\"Verify that provided arguments is a valid IDisplay call.\n\n    :param str prompt: prompt for the user\n    :param default: default answer to prompt\n    :param str cli_flag: command line option for setting an answer\n        to this question\n    :param bool force_interactive: if interactivity is forced by the\n        IDisplay call\n\n    \"\"\"\n    msg = \"Invalid IDisplay call for this prompt:\\n{0}\".format(prompt)\n    if cli_flag:\n        msg += (\"\\nYou can set an answer to \"\n                \"this prompt with the {0} flag\".format(cli_flag))\n    assert default is not None or force_interactive, msg\n\n\n# This class takes a similar approach to the cryptography project to deprecate attributes\n# in public modules. See the _ModuleWithDeprecation class here:\n# https://github.com/pyca/cryptography/blob/91105952739442a74582d3e62b3d2111365b0dc7/src/cryptography/utils.py#L129\nclass _DisplayUtilDeprecationModule:\n    \"\"\"\n    Internal class delegating to a module, and displaying warnings when attributes\n    related to deprecated attributes in the certbot.display.util module.\n    \"\"\"\n    def __init__(self, module):\n        self.__dict__['_module'] = module\n\n    def __getattr__(self, attr):\n        if attr in ('FileDisplay', 'NoninteractiveDisplay', 'SIDE_FRAME', 'input_with_timeout',\n                    'separate_list_input', 'summarize_domain_list', 'WIDTH', 'HELP', 'ESC'):\n            warnings.warn('{0} attribute in certbot.display.util module is deprecated '\n                          'and will be removed soon.'.format(attr),\n                          DeprecationWarning, stacklevel=2)\n        return getattr(self._module, attr)\n\n    def __setattr__(self, attr, value):  # pragma: no cover\n        setattr(self._module, attr, value)\n\n    def __delattr__(self, attr):  # pragma: no cover\n        delattr(self._module, attr)\n\n    def __dir__(self):  # pragma: no cover\n        return ['_module'] + dir(self._module)\n\n\n# Patching ourselves to warn about deprecation and planned removal of some elements in the module.\nsys.modules[__name__] = cast(ModuleType, _DisplayUtilDeprecationModule(sys.modules[__name__]))\n", "path": "certbot/certbot/display/util.py"}]}