Repository: hikari-py/hikari (python)

Issue:
Add option to supress optimization warning message
### Summary

The warning introduced by #1431 can be annoying in some context (for example code analysis that needs runtime evaluation, like [slotscheck](https://slotscheck.readthedocs.io/en/latest/)).

I assume there may be some other use cases for wanting to disable the warning (dev platform running without optimization, etc)

### Why is this needed?

Other features can be disabled iirc, like the check for update call or the banner. More choice seems better in that case.

### Ideal implementation

Using the same mechanism as banner deactivation?

### Checklist

- [X] I have searched the issue tracker and have made sure it's not a duplicate. If it is a follow up of another issue, I have specified it.

Pull request:
Add ability to suppress optimization warnings
### Summary
<!-- Small summary of the merge request -->
This PR adds the ability to suppress optimization warnings by passing `suppress_optimization_warning=True` to the `GatewayBot` and `RESTBot` constructors.

### Checklist
<!-- Make sure to tick all the following boxes by putting an `x` in between (like this `[x]`) -->
- [x] I have run `nox` and all the pipelines have passed.
- [x] I have made unittests according to the code I have added/modified/deleted.

### Related issues
<!--
To mention an issue use `#issue-id` and to mention a merge request use `!merge-request-id`
To close/fix an issue use `Close #issue-id` or `Fix #issue-id` (depending on the merge request)
-->
Closes #1446.


Patch:
diff --git a/changes/1459.feature.md b/changes/1459.feature.md
new file mode 100644
index 00000000..1bc2dffe
--- /dev/null
+++ b/changes/1459.feature.md
@@ -0,0 +1,1 @@
+Add ability to suppress optimization warnings through `suppress_optimization_warning=True` to the `GatewayBot` or `RESTBot` constructors.
diff --git a/hikari/impl/bot.py b/hikari/impl/bot.py
index 68455d52..e597d4d3 100644
--- a/hikari/impl/bot.py
+++ b/hikari/impl/bot.py
@@ -147,6 +147,10 @@ class GatewayBot(traits.GatewayBotAware):
         The package to search for a `banner.txt` in. Defaults to `"hikari"` for
         the `"hikari/banner.txt"` banner.
         Setting this to `None` will disable the banner being shown.
+    suppress_optimization_warning : bool
+        Defaults to `False`. By default, Hikari warns you if you are not running
+        your bot using optimizations (`-O` or `-OO`). If this is `True`, you won't
+        receive these warnings, even if you are not running using optimizations.
     executor : typing.Optional[concurrent.futures.Executor]
         Defaults to `None`. If non-`None`, then this executor
         is used instead of the `concurrent.futures.ThreadPoolExecutor` attached
@@ -296,6 +300,7 @@ def __init__(
         *,
         allow_color: bool = True,
         banner: typing.Optional[str] = "hikari",
+        suppress_optimization_warning: bool = False,
         executor: typing.Optional[concurrent.futures.Executor] = None,
         force_color: bool = False,
         cache_settings: typing.Optional[config_impl.CacheSettings] = None,
@@ -311,7 +316,7 @@ def __init__(
         # Beautification and logging
         ux.init_logging(logs, allow_color, force_color)
         self.print_banner(banner, allow_color, force_color)
-        ux.warn_if_not_optimized()
+        ux.warn_if_not_optimized(suppress_optimization_warning)
 
         # Settings and state
         self._closed_event: typing.Optional[asyncio.Event] = None
diff --git a/hikari/impl/rest_bot.py b/hikari/impl/rest_bot.py
index 24eb8e3c..8ee35fbc 100644
--- a/hikari/impl/rest_bot.py
+++ b/hikari/impl/rest_bot.py
@@ -99,6 +99,10 @@ class RESTBot(traits.RESTBotAware, interaction_server_.InteractionServer):
         The package to search for a `banner.txt` in. Defaults to `"hikari"` for
         the `"hikari/banner.txt"` banner.
         Setting this to `None` will disable the banner being shown.
+    suppress_optimization_warning : bool
+        Defaults to `False`. By default, Hikari warns you if you are not running
+        your bot using optimizations (`-O` or `-OO`). If this is `True`, you won't
+        receive these warnings, even if you are not running using optimizations.
     executor : typing.Optional[concurrent.futures.Executor]
         Defaults to `None`. If non-`None`, then this executor
         is used instead of the `concurrent.futures.ThreadPoolExecutor` attached
@@ -205,6 +209,7 @@ def __init__(
         public_key: typing.Union[bytes, str, None] = None,
         allow_color: bool = True,
         banner: typing.Optional[str] = "hikari",
+        suppress_optimization_warning: bool = False,
         executor: typing.Optional[concurrent.futures.Executor] = None,
         force_color: bool = False,
         http_settings: typing.Optional[config_impl.HTTPSettings] = None,
@@ -225,6 +230,7 @@ def __init__(
         *,
         allow_color: bool = True,
         banner: typing.Optional[str] = "hikari",
+        suppress_optimization_warning: bool = False,
         executor: typing.Optional[concurrent.futures.Executor] = None,
         force_color: bool = False,
         http_settings: typing.Optional[config_impl.HTTPSettings] = None,
@@ -244,6 +250,7 @@ def __init__(
         *,
         allow_color: bool = True,
         banner: typing.Optional[str] = "hikari",
+        suppress_optimization_warning: bool = False,
         executor: typing.Optional[concurrent.futures.Executor] = None,
         force_color: bool = False,
         http_settings: typing.Optional[config_impl.HTTPSettings] = None,
@@ -262,7 +269,7 @@ def __init__(
         # Beautification and logging
         ux.init_logging(logs, allow_color, force_color)
         self.print_banner(banner, allow_color, force_color)
-        ux.warn_if_not_optimized()
+        ux.warn_if_not_optimized(suppress_optimization_warning)
 
         # Settings and state
         self._close_event: typing.Optional[asyncio.Event] = None
diff --git a/hikari/internal/ux.py b/hikari/internal/ux.py
index 273bd3af..b7e0c459 100644
--- a/hikari/internal/ux.py
+++ b/hikari/internal/ux.py
@@ -242,9 +242,9 @@ def print_banner(
         stdout.flush()
 
 
-def warn_if_not_optimized() -> None:
+def warn_if_not_optimized(suppress: bool) -> None:
     """Log a warning if not running in optimization mode."""
-    if __debug__:
+    if __debug__ and not suppress:
         _LOGGER.warning(
             "You are running on optimization level 0 (no optimizations), which may slow down your application. "
             "For production, consider using at least level 1 optimization by passing `-O` to the python call."


Test patch:
diff --git a/tests/hikari/impl/test_bot.py b/tests/hikari/impl/test_bot.py
index ff130973..4cbb4577 100644
--- a/tests/hikari/impl/test_bot.py
+++ b/tests/hikari/impl/test_bot.py
@@ -190,6 +190,7 @@ def test_init(self):
                 "token",
                 allow_color=False,
                 banner="testing",
+                suppress_optimization_warning=True,
                 executor=executor,
                 force_color=True,
                 cache_settings=cache_settings,
@@ -237,7 +238,7 @@ def test_init(self):
 
         init_logging.assert_called_once_with("DEBUG", False, True)
         print_banner.assert_called_once_with("testing", False, True)
-        warn_if_not_optimized.assert_called_once_with()
+        warn_if_not_optimized.assert_called_once_with(True)
 
     def test_init_when_no_settings(self):
         stack = contextlib.ExitStack()
diff --git a/tests/hikari/impl/test_rest_bot.py b/tests/hikari/impl/test_rest_bot.py
index ef60c4fc..2d846aaf 100644
--- a/tests/hikari/impl/test_rest_bot.py
+++ b/tests/hikari/impl/test_rest_bot.py
@@ -120,6 +120,7 @@ def test___init__(
                 b"2123123123123132",
                 allow_color=False,
                 banner="a banner",
+                suppress_optimization_warning=True,
                 executor=mock_executor,
                 force_color=True,
                 http_settings=mock_http_settings,
@@ -131,6 +132,7 @@ def test___init__(
             )
 
             ux.init_logging.assert_called_once_with("ERROR", False, True)
+            ux.warn_if_not_optimized.assert_called_once_with(True)
             entity_factory_impl.EntityFactoryImpl.assert_called_once_with(result)
             rest_impl.RESTClientImpl.assert_called_once_with(
                 cache=None,
diff --git a/tests/hikari/internal/test_ux.py b/tests/hikari/internal/test_ux.py
index 7a0dad2c..76af98a8 100644
--- a/tests/hikari/internal/test_ux.py
+++ b/tests/hikari/internal/test_ux.py
@@ -376,14 +376,21 @@ class TestWarnIfNotOptimized:
     @pytest.mark.skipif(not __debug__, reason="Not running in optimized mode")
     def test_when_not_optimized(self):
         with mock.patch.object(ux, "_LOGGER") as logger:
-            ux.warn_if_not_optimized()
+            ux.warn_if_not_optimized(suppress=False)
 
         logger.warning.assert_called()
 
     @pytest.mark.skipif(__debug__, reason="Running in optimized mode")
     def test_when_optimized(self):
         with mock.patch.object(ux, "_LOGGER") as logger:
-            ux.warn_if_not_optimized()
+            ux.warn_if_not_optimized(suppress=False)
+
+        logger.warning.assert_not_called()
+
+    @pytest.mark.skipif(not __debug__, reason="Not running in optimized mode")
+    def test_when_optimized_and_suppressed(self):
+        with mock.patch.object(ux, "_LOGGER") as logger:
+            ux.warn_if_not_optimized(suppress=True)
 
         logger.warning.assert_not_called()