Repository: sopel-irc/sopel

Issue:
cli: `--quiet` arg doesn't do anything
### Description

Between 6.x and 7.0, when the CLI and logging stuff was rewritten, it appears that the `--quiet` argument's function got lost. It's still parsed and stored in the options when `argparse` processes the command line for `sopel start`, `sopel stop`, etc., but the `opts.quiet` flag is never used.

Even in the current `master` branch, using `sopel.cli.run.command_start()` as an example (the other subcommands are similar), `opts` is passed to the `get_configuration()` helper and then the only remaining reference to it is here:

https://github.com/sopel-irc/sopel/blob/94065d7fb2aaafb946c98e4542a5fc7dbfb4a499/sopel/cli/run.py#L327-L330

However, note the following `run_script.py` code from 6.x, which uses `OutputRedirect` (a now-unused class that was just formally marked deprecated in #2385):

https://github.com/sopel-irc/sopel/blob/592735d4ea61f61212a9e5d1ae5f0a90c6f07983/sopel/run_script.py#L152-L153

It looks like this goes all the way back to #1678, and has therefore been broken since 7.0.0. That's when the output redirection was replaced by a setup function (`sopel.logger.setup_logging()`) that takes only the bot's Config into account and does not receive any arguments from the CLI.

### Reproduction steps

1. Run `sopel start --quiet`
2. The bot prints output to the terminal

### Expected behavior

The bot should not print output to the terminal; help text for `--quiet` says that it should "Suppress all output".

### Relevant logs

_No response_

### Notes

It's funny that we have tests to make sure the `--quiet` argument is parsed and present in the resulting `opts` object, but never got around to a functional test that actually checks whether it quiets the bot's output.

I guess how long it took to discover this shows you just how few people actually use `--quiet`… including me. (#1678 was merged over 3 years ago.) Before tonight, I have no idea when or even if I've ever used that flag.

In the end, we need to either _fix it_ in 8.0 or _remove it entirely_.

### Sopel version

94065d7fb2aaafb946c98e4542a5fc7dbfb4a499

### Installation method

`pip install`

### Python version

_No response_

### Operating system

_No response_

### IRCd

_No response_

### Relevant plugins

_No response_


Discussion:
I'm for removing it. If someone wants to suppress output, they can do `sopel start >/dev/null 2>&1`.

Resolving patch:
diff --git a/sopel/cli/run.py b/sopel/cli/run.py
--- a/sopel/cli/run.py
+++ b/sopel/cli/run.py
@@ -127,11 +127,6 @@ def build_parser():
              'background. The instance will be named after the name of the '
              'configuration file used to run it. '
              'To stop it, use ``sopel stop`` (with the same configuration).')
-    parser_start.add_argument(
-        '--quiet',
-        action="store_true",
-        dest="quiet",
-        help="Suppress all output")
     utils.add_common_arguments(parser_start)
 
     # manage `configure` subcommand
@@ -166,11 +161,6 @@ def build_parser():
         action='store_true',
         default=False,
         help='Kill Sopel without a graceful quit')
-    parser_stop.add_argument(
-        '--quiet',
-        action="store_true",
-        dest="quiet",
-        help="Suppress all output")
     utils.add_common_arguments(parser_stop)
 
     # manage `restart` subcommand
@@ -178,11 +168,6 @@ def build_parser():
         'restart',
         description='Restart a running Sopel instance',
         help='Restart a running Sopel instance')
-    parser_restart.add_argument(
-        '--quiet',
-        action="store_true",
-        dest="quiet",
-        help="Suppress all output")
     utils.add_common_arguments(parser_restart)
 
     return parser


Test patch:
diff --git a/test/cli/test_cli_run.py b/test/cli/test_cli_run.py
--- a/test/cli/test_cli_run.py
+++ b/test/cli/test_cli_run.py
@@ -62,12 +62,10 @@ def test_build_parser_start():
     assert hasattr(options, 'config')
     assert hasattr(options, 'configdir')
     assert hasattr(options, 'daemonize')
-    assert hasattr(options, 'quiet')
 
     assert options.config == 'default'
     assert options.configdir == config.DEFAULT_HOMEDIR
     assert options.daemonize is False
-    assert options.quiet is False
 
 
 def test_build_parser_start_config():
@@ -97,13 +95,6 @@ def test_build_parser_start_daemonize():
     assert options.daemonize is True
 
 
-def test_build_parser_start_quiet():
-    parser = build_parser()
-
-    options = parser.parse_args(['start', '--quiet'])
-    assert options.quiet is True
-
-
 def test_build_parser_stop():
     """Assert parser's namespace exposes stop's options (default values)"""
     parser = build_parser()
@@ -113,12 +104,10 @@ def test_build_parser_stop():
     assert hasattr(options, 'config')
     assert hasattr(options, 'configdir')
     assert hasattr(options, 'kill')
-    assert hasattr(options, 'quiet')
 
     assert options.config == 'default'
     assert options.configdir == config.DEFAULT_HOMEDIR
     assert options.kill is False
-    assert options.quiet is False
 
 
 def test_build_parser_stop_config():
@@ -148,13 +137,6 @@ def test_build_parser_stop_kill():
     assert options.kill is True
 
 
-def test_build_parser_stop_quiet():
-    parser = build_parser()
-
-    options = parser.parse_args(['stop', '--quiet'])
-    assert options.quiet is True
-
-
 def test_build_parser_restart():
     """Assert parser's namespace exposes restart's options (default values)"""
     parser = build_parser()
@@ -163,11 +145,9 @@ def test_build_parser_restart():
     assert isinstance(options, argparse.Namespace)
     assert hasattr(options, 'config')
     assert hasattr(options, 'configdir')
-    assert hasattr(options, 'quiet')
 
     assert options.config == 'default'
     assert options.configdir == config.DEFAULT_HOMEDIR
-    assert options.quiet is False
 
 
 def test_build_parser_restart_config():
@@ -187,13 +167,6 @@ def test_build_parser_restart_configdir():
     assert options.configdir == 'custom'
 
 
-def test_build_parser_restart_quiet():
-    parser = build_parser()
-
-    options = parser.parse_args(['restart', '--quiet'])
-    assert options.quiet is True
-
-
 def test_build_parser_configure():
     """Assert parser's namespace exposes configure's options (default values)"""
     parser = build_parser()