Repository: sanic-org/sanic

Issue:
distutils.strtobool deprecation 
**Describe the bug**
he distutils package is deprecated and slated for removal in Python 3.12. [PEP 632](https://www.python.org/dev/peps/pep-0632/)

**Code snippet**
[sanic/server/loop.py](https://github.com/sanic-org/sanic/blob/ac388d644b1e22156e228470fad8ea34932c080a/sanic/server/loop.py#L3)

**Expected behavior**
A lack of warnings about deprecation

**Environment (please complete the following information):**
 - OS: All
 - Version: All supported as of 2022/01/23 

**Additional context**
This is housekeeping to clean up a core python deprecation.



Discussion:
Note: Even though this is an exceptionally minor fix, I don't feel like this should be backported to 20.12LTS. 20.12LTS will sunset long before 3.12 is past alpha (and possibly before 3.11.0 final hits, depending on if the timeline in [PEP 664](https://www.python.org/dev/peps/pep-0664/) is hit or not) and that makes it likely that 21.12LTS will be the only backport needed, if any.
No backport will be needed because 21.12 does not (an will not) purport to support 3.12. It is 3.7-3.10 and that will not change. We probably should add Python versions here: https://sanic.dev/en/org/policies.html#release-schedule.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If this  is incorrect, please respond with an update. Thank you for your contributions.

I think we still need to fix this, right? Any update?
This is still something to do, just not something that we need to release back to the LTS.
I'll resurrect this, completely forgot about it.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If this  is incorrect, please respond with an update. Thank you for your contributions.

This is still an issue: https://github.com/sanic-org/sanic/blob/4726cf1910fe7735ac0944504b02fc4f3d89d5fd/sanic/server/loop.py#L4
Anyone want to take a crack at this in the next couple days to get into the LTS?

Resolving patch:
diff --git a/sanic/server/loop.py b/sanic/server/loop.py
--- a/sanic/server/loop.py
+++ b/sanic/server/loop.py
@@ -1,11 +1,11 @@
 import asyncio
 import sys
 
-from distutils.util import strtobool
 from os import getenv
 
 from sanic.compat import OS_IS_WINDOWS
 from sanic.log import error_logger
+from sanic.utils import str_to_bool
 
 
 def try_use_uvloop() -> None:
@@ -35,7 +35,7 @@ def try_use_uvloop() -> None:
         )
         return
 
-    uvloop_install_removed = strtobool(getenv("SANIC_NO_UVLOOP", "no"))
+    uvloop_install_removed = str_to_bool(getenv("SANIC_NO_UVLOOP", "no"))
     if uvloop_install_removed:
         error_logger.info(
             "You are requesting to run Sanic using uvloop, but the "
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -6,8 +6,6 @@
 import re
 import sys
 
-from distutils.util import strtobool
-
 from setuptools import find_packages, setup
 from setuptools.command.test import test as TestCommand
 
@@ -37,6 +35,25 @@ def open_local(paths, mode="r", encoding="utf8"):
 
     return codecs.open(path, mode, encoding)
 
+def str_to_bool(val: str) -> bool:
+    val = val.lower()
+    if val in {
+        "y",
+        "yes",
+        "yep",
+        "yup",
+        "t",
+        "true",
+        "on",
+        "enable",
+        "enabled",
+        "1",
+    }:
+        return True
+    elif val in {"n", "no", "f", "false", "off", "disable", "disabled", "0"}:
+        return False
+    else:
+        raise ValueError(f"Invalid truth value {val}")
 
 with open_local(["sanic", "__version__.py"], encoding="latin1") as fp:
     try:
@@ -131,13 +148,13 @@ def open_local(paths, mode="r", encoding="utf8"):
 
 all_require = list(set(dev_require + docs_require))
 
-if strtobool(os.environ.get("SANIC_NO_UJSON", "no")):
+if str_to_bool(os.environ.get("SANIC_NO_UJSON", "no")):
     print("Installing without uJSON")
     requirements.remove(ujson)
     tests_require.remove(types_ujson)
 
 # 'nt' means windows OS
-if strtobool(os.environ.get("SANIC_NO_UVLOOP", "no")):
+if str_to_bool(os.environ.get("SANIC_NO_UVLOOP", "no")):
     print("Installing without uvLoop")
     requirements.remove(uvloop)
 


Test patch: