Repository: twisted/twisted

Issue:
Idea: Remove `_get_async_param` method
**Is your feature request related to a problem? Please describe.**

An idea to cleanup the project. `_get_async_param()` was added in Twisted 18.9.0 to mitigate an issue where Python 3.7 introduced the `async` keyword which caused problem where variables were trying to use that name also. 

Now that Twisted supports only Python 3.8+ would it make sense to remove this method since all supported Python versions now include the `async` keyword? Or is Twisted stuck with this API change?

See: https://github.com/twisted/twisted/issues/9384

If it is acceptable to remove it, I can submit a PR for it.



Discussion:
Hi, Thanks for the ticket.
Any cleanup PR is much appreciated.

Looking forward to review the PR. Thanks again!

Resolving patch:
diff --git a/src/twisted/conch/manhole.py b/src/twisted/conch/manhole.py
--- a/src/twisted/conch/manhole.py
+++ b/src/twisted/conch/manhole.py
@@ -23,7 +23,6 @@
 
 from twisted.conch import recvline
 from twisted.internet import defer
-from twisted.python.compat import _get_async_param
 from twisted.python.htmlizer import TokenPrinter
 from twisted.python.monkey import MonkeyPatcher
 
@@ -161,8 +160,7 @@ def _ebDisplayDeferred(self, failure, k, obj):
         del self._pendingDeferreds[id(obj)]
         return failure
 
-    def write(self, data, isAsync=None, **kwargs):
-        isAsync = _get_async_param(isAsync, **kwargs)
+    def write(self, data, isAsync=None):
         self.handler.addOutput(data, isAsync)
 
 
@@ -239,8 +237,7 @@ def _needsNewline(self):
         w = self.terminal.lastWrite
         return not w.endswith(b"\n") and not w.endswith(b"\x1bE")
 
-    def addOutput(self, data, isAsync=None, **kwargs):
-        isAsync = _get_async_param(isAsync, **kwargs)
+    def addOutput(self, data, isAsync=None):
         if isAsync:
             self.terminal.eraseLine()
             self.terminal.cursorBackward(len(self.lineBuffer) + len(self.ps[self.pn]))
diff --git a/src/twisted/mail/imap4.py b/src/twisted/mail/imap4.py
--- a/src/twisted/mail/imap4.py
+++ b/src/twisted/mail/imap4.py
@@ -80,7 +80,6 @@
 from twisted.protocols import basic, policies
 from twisted.python import log, text
 from twisted.python.compat import (
-    _get_async_param,
     _matchingString,
     iterbytes,
     nativeString,
@@ -1076,8 +1075,7 @@ def sendPositiveResponse(self, tag=None, message=b""):
     def sendNegativeResponse(self, tag=None, message=b""):
         self._respond(b"NO", tag, message)
 
-    def sendUntaggedResponse(self, message, isAsync=None, **kwargs):
-        isAsync = _get_async_param(isAsync, **kwargs)
+    def sendUntaggedResponse(self, message, isAsync=None):
         if not isAsync or (self.blocked is None):
             self._respond(message, None, None)
         else:
diff --git a/src/twisted/python/compat.py b/src/twisted/python/compat.py
--- a/src/twisted/python/compat.py
+++ b/src/twisted/python/compat.py
@@ -27,7 +27,6 @@
 import platform
 import socket
 import urllib.parse as urllib_parse
-import warnings
 from collections.abc import Sequence
 from functools import reduce
 from html import escape
@@ -497,35 +496,6 @@ def _constructMethod(cls, name, self):
     return _MethodType(func, self)
 
 
-def _get_async_param(isAsync=None, **kwargs):
-    """
-    Provide a backwards-compatible way to get async param value that does not
-    cause a syntax error under Python 3.7.
-
-    @param isAsync: isAsync param value (should default to None)
-    @type isAsync: L{bool}
-
-    @param kwargs: keyword arguments of the caller (only async is allowed)
-    @type kwargs: L{dict}
-
-    @raise TypeError: Both isAsync and async specified.
-
-    @return: Final isAsync param value
-    @rtype: L{bool}
-    """
-    if "async" in kwargs:
-        warnings.warn(
-            "'async' keyword argument is deprecated, please use isAsync",
-            DeprecationWarning,
-            stacklevel=2,
-        )
-    if isAsync is None and "async" in kwargs:
-        isAsync = kwargs.pop("async")
-    if kwargs:
-        raise TypeError
-    return bool(isAsync)
-
-
 def _pypy3BlockingHack():
     """
     Work around U{https://foss.heptapod.net/pypy/pypy/-/issues/3051}
@@ -645,6 +615,5 @@ def fromFDWithoutModifyingFlags(fd, family, type, proto=None):
     "intern",
     "unichr",
     "raw_input",
-    "_get_async_param",
     "Sequence",
 ]


Test patch:
diff --git a/src/twisted/test/test_compat.py b/src/twisted/test/test_compat.py
--- a/src/twisted/test/test_compat.py
+++ b/src/twisted/test/test_compat.py
@@ -15,7 +15,6 @@
 
 from twisted.python.compat import (
     _PYPY,
-    _get_async_param,
     bytesEnviron,
     cmp,
     comparable,
@@ -547,34 +546,3 @@ def test_alwaysBytes(self):
             types.add(type(val))
 
         self.assertEqual(list(types), [bytes])
-
-
-class GetAsyncParamTests(SynchronousTestCase):
-    """
-    Tests for L{twisted.python.compat._get_async_param}
-    """
-
-    def test_get_async_param(self):
-        """
-        L{twisted.python.compat._get_async_param} uses isAsync by default,
-        or deprecated async keyword argument if isAsync is None.
-        """
-        self.assertEqual(_get_async_param(isAsync=False), False)
-        self.assertEqual(_get_async_param(isAsync=True), True)
-        self.assertEqual(_get_async_param(isAsync=None, **{"async": False}), False)
-        self.assertEqual(_get_async_param(isAsync=None, **{"async": True}), True)
-        self.assertRaises(TypeError, _get_async_param, False, {"async": False})
-
-    def test_get_async_param_deprecation(self):
-        """
-        L{twisted.python.compat._get_async_param} raises a deprecation
-        warning if async keyword argument is passed.
-        """
-        self.assertEqual(_get_async_param(isAsync=None, **{"async": False}), False)
-        currentWarnings = self.flushWarnings(
-            offendingFunctions=[self.test_get_async_param_deprecation]
-        )
-        self.assertEqual(
-            currentWarnings[0]["message"],
-            "'async' keyword argument is deprecated, please use isAsync",
-        )