Repository: certbot/certbot

Issue:
Unexport various internal attributes in certbot.display.util
> The attributes FileDisplay, NoninteractiveDisplay, SIDE_FRAME, input_with_timeout, separate_list_input, summarize_domain_list, WIDTH, HELP, and ESC from certbot.display.util will be removed.

https://github.com/certbot/certbot/blob/5c111d0bd1206d864d7cb93754e101f6073bc669/certbot/certbot/display/util.py#L23-L31


Discussion:

Resolving patch:
diff --git a/certbot/certbot/_internal/main.py b/certbot/certbot/_internal/main.py
--- a/certbot/certbot/_internal/main.py
+++ b/certbot/certbot/_internal/main.py
@@ -1654,8 +1654,8 @@ def make_or_verify_needed_dirs(config: configuration.NamespaceConfig) -> None:
 
 @contextmanager
 def make_displayer(config: configuration.NamespaceConfig
-                   ) -> Generator[Union[display_util.NoninteractiveDisplay,
-                                        display_util.FileDisplay], None, None]:
+                   ) -> Generator[Union[display_obj.NoninteractiveDisplay,
+                                        display_obj.FileDisplay], None, None]:
     """Creates a display object appropriate to the flags in the supplied config.
 
     :param config: Configuration object
@@ -1663,18 +1663,18 @@ def make_displayer(config: configuration.NamespaceConfig
     :returns: Display object
 
     """
-    displayer: Union[None, display_util.NoninteractiveDisplay,
-                     display_util.FileDisplay] = None
+    displayer: Union[None, display_obj.NoninteractiveDisplay,
+                     display_obj.FileDisplay] = None
     devnull: Optional[IO] = None
 
     if config.quiet:
         config.noninteractive_mode = True
         devnull = open(os.devnull, "w")  # pylint: disable=consider-using-with
-        displayer = display_util.NoninteractiveDisplay(devnull)
+        displayer = display_obj.NoninteractiveDisplay(devnull)
     elif config.noninteractive_mode:
-        displayer = display_util.NoninteractiveDisplay(sys.stdout)
+        displayer = display_obj.NoninteractiveDisplay(sys.stdout)
     else:
-        displayer = display_util.FileDisplay(
+        displayer = display_obj.FileDisplay(
             sys.stdout, config.force_interactive)
 
     try:
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,26 +9,12 @@
 Other messages can use the `logging` module. See `log.py`.
 
 """
-import sys
-from types import ModuleType
-from typing import Any
-from typing import cast
 from typing import List
 from typing import Optional
 from typing import Tuple
 from typing import Union
-import warnings
 
 from certbot._internal.display import obj
-# These specific imports from certbot._internal.display.obj and
-# certbot._internal.display.util are done to not break the public API of this
-# module.
-from certbot._internal.display.obj import FileDisplay  # pylint: disable=unused-import
-from certbot._internal.display.obj import NoninteractiveDisplay  # pylint: disable=unused-import
-from certbot._internal.display.obj import SIDE_FRAME  # pylint: disable=unused-import
-from certbot._internal.display.util import input_with_timeout  # pylint: disable=unused-import
-from certbot._internal.display.util import separate_list_input  # pylint: disable=unused-import
-from certbot._internal.display.util import summarize_domain_list  # pylint: disable=unused-import
 
 # 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.
@@ -38,17 +24,8 @@
 CANCEL = obj.CANCEL
 """Display exit code for a user canceling the display."""
 
-# These constants are unused and should be removed in a major release of
-# Certbot.
 WIDTH = 72
 
-HELP = "help"
-"""Display exit code when for when the user requests more help. (UNUSED)"""
-
-ESC = "esc"
-"""Display exit code when the user hits Escape (UNUSED)"""
-
-
 def notify(msg: str) -> None:
     """Display a basic status message.
 
@@ -204,36 +181,3 @@ def assert_valid_call(prompt: str, default: str, cli_flag: str, force_interactiv
         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: ModuleType) -> None:
-        self.__dict__['_module'] = module
-
-    def __getattr__(self, attr: str) -> Any:
-        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: str, value: Any) -> None:  # pragma: no cover
-        setattr(self._module, attr, value)
-
-    def __delattr__(self, attr: str) -> None:  # pragma: no cover
-        delattr(self._module, attr)
-
-    def __dir__(self) -> List[str]:  # 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__]))


Test patch:
diff --git a/certbot-compatibility-test/certbot_compatibility_test/test_driver.py b/certbot-compatibility-test/certbot_compatibility_test/test_driver.py
--- a/certbot-compatibility-test/certbot_compatibility_test/test_driver.py
+++ b/certbot-compatibility-test/certbot_compatibility_test/test_driver.py
@@ -33,7 +33,6 @@
 from certbot import achallenges
 from certbot import errors as le_errors
 from certbot._internal.display import obj as display_obj
-from certbot.display import util as display_util
 from certbot.tests import acme_util
 
 DESCRIPTION = """
@@ -339,7 +338,7 @@ def setup_logging(args: argparse.Namespace) -> None:
 
 def setup_display() -> None:
     """"Prepares a display utility instance for the Certbot plugins """
-    displayer = display_util.NoninteractiveDisplay(sys.stdout)
+    displayer = display_obj.NoninteractiveDisplay(sys.stdout)
     display_obj.set_display(displayer)
 
 
diff --git a/certbot/tests/display/obj_test.py b/certbot/tests/display/obj_test.py
--- a/certbot/tests/display/obj_test.py
+++ b/certbot/tests/display/obj_test.py
@@ -275,7 +275,7 @@ class NoninteractiveDisplayTest(unittest.TestCase):
     """Test non-interactive display. These tests are pretty easy!"""
     def setUp(self):
         self.mock_stdout = mock.MagicMock()
-        self.displayer = display_util.NoninteractiveDisplay(self.mock_stdout)
+        self.displayer = display_obj.NoninteractiveDisplay(self.mock_stdout)
 
     @mock.patch("certbot._internal.display.obj.logger")
     def test_notification_no_pause(self, mock_logger):