We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
tornado.platform.twisted disappeared but did not explain its replacement
Many years' worth of documentation explains that folks can do

```
from tornado.platform.twisted import install
reactor = install()
```

I can see that in https://github.com/tornadoweb/tornado/commit/004de9c301cc4c2dae4d8f2507af1851d0c9763a#diff-77b5a8a33248ef0bcafbc1bb71e9f013 Twisted integration was removed, since we can all depend on the stdlib loop APIs.  This is great, but it also breaks a bunch of Jupyter notebooks, tutorials, etc.

Could you be convinced to replace all those sprawling APIs with something like this:

```python3
def install():
    from twisted.internet.asyncioreactor import install
    install()
    from twisted.internet import reactor
    reactor.startRunning()
    return reactor
```

possibly with a `warnings.warn` explaining that users could just call these APIs directly, if that's the desired end-state?

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `tornado/platform/twisted.py`
Content:
```
1 # Licensed under the Apache License, Version 2.0 (the "License"); you may
2 # not use this file except in compliance with the License. You may obtain
3 # a copy of the License at
4 #
5 #     http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 # License for the specific language governing permissions and limitations
11 # under the License.
12 """Bridges between the Twisted package and Tornado.
13 """
14 
15 import socket
16 import sys
17 
18 import twisted.internet.abstract  # type: ignore
19 import twisted.internet.asyncioreactor  # type: ignore
20 from twisted.internet.defer import Deferred  # type: ignore
21 from twisted.python import failure  # type: ignore
22 import twisted.names.cache  # type: ignore
23 import twisted.names.client  # type: ignore
24 import twisted.names.hosts  # type: ignore
25 import twisted.names.resolve  # type: ignore
26 
27 
28 from tornado.concurrent import Future, future_set_exc_info
29 from tornado.escape import utf8
30 from tornado import gen
31 from tornado.netutil import Resolver
32 
33 import typing
34 
35 if typing.TYPE_CHECKING:
36     from typing import Generator, Any, List, Tuple  # noqa: F401
37 
38 
39 class TwistedResolver(Resolver):
40     """Twisted-based asynchronous resolver.
41 
42     This is a non-blocking and non-threaded resolver.  It is
43     recommended only when threads cannot be used, since it has
44     limitations compared to the standard ``getaddrinfo``-based
45     `~tornado.netutil.Resolver` and
46     `~tornado.netutil.DefaultExecutorResolver`.  Specifically, it returns at
47     most one result, and arguments other than ``host`` and ``family``
48     are ignored.  It may fail to resolve when ``family`` is not
49     ``socket.AF_UNSPEC``.
50 
51     Requires Twisted 12.1 or newer.
52 
53     .. versionchanged:: 5.0
54        The ``io_loop`` argument (deprecated since version 4.1) has been removed.
55     """
56 
57     def initialize(self) -> None:
58         # partial copy of twisted.names.client.createResolver, which doesn't
59         # allow for a reactor to be passed in.
60         self.reactor = twisted.internet.asyncioreactor.AsyncioSelectorReactor()
61 
62         host_resolver = twisted.names.hosts.Resolver("/etc/hosts")
63         cache_resolver = twisted.names.cache.CacheResolver(reactor=self.reactor)
64         real_resolver = twisted.names.client.Resolver(
65             "/etc/resolv.conf", reactor=self.reactor
66         )
67         self.resolver = twisted.names.resolve.ResolverChain(
68             [host_resolver, cache_resolver, real_resolver]
69         )
70 
71     @gen.coroutine
72     def resolve(
73         self, host: str, port: int, family: int = 0
74     ) -> "Generator[Any, Any, List[Tuple[int, Any]]]":
75         # getHostByName doesn't accept IP addresses, so if the input
76         # looks like an IP address just return it immediately.
77         if twisted.internet.abstract.isIPAddress(host):
78             resolved = host
79             resolved_family = socket.AF_INET
80         elif twisted.internet.abstract.isIPv6Address(host):
81             resolved = host
82             resolved_family = socket.AF_INET6
83         else:
84             deferred = self.resolver.getHostByName(utf8(host))
85             fut = Future()  # type: Future[Any]
86             deferred.addBoth(fut.set_result)
87             resolved = yield fut
88             if isinstance(resolved, failure.Failure):
89                 try:
90                     resolved.raiseException()
91                 except twisted.names.error.DomainError as e:
92                     raise IOError(e)
93             elif twisted.internet.abstract.isIPAddress(resolved):
94                 resolved_family = socket.AF_INET
95             elif twisted.internet.abstract.isIPv6Address(resolved):
96                 resolved_family = socket.AF_INET6
97             else:
98                 resolved_family = socket.AF_UNSPEC
99         if family != socket.AF_UNSPEC and family != resolved_family:
100             raise Exception(
101                 "Requested socket family %d but got %d" % (family, resolved_family)
102             )
103         result = [(typing.cast(int, resolved_family), (resolved, port))]
104         return result
105 
106 
107 if hasattr(gen.convert_yielded, "register"):
108 
109     @gen.convert_yielded.register(Deferred)  # type: ignore
110     def _(d: Deferred) -> Future:
111         f = Future()  # type: Future[Any]
112 
113         def errback(failure: failure.Failure) -> None:
114             try:
115                 failure.raiseException()
116                 # Should never happen, but just in case
117                 raise Exception("errback called without error")
118             except:
119                 future_set_exc_info(f, sys.exc_info())
120 
121         d.addCallbacks(f.set_result, errback)
122         return f
123
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/tornado/platform/twisted.py b/tornado/platform/twisted.py
--- a/tornado/platform/twisted.py
+++ b/tornado/platform/twisted.py
@@ -104,6 +104,30 @@
         return result
 
 
+def install() -> None:
+    """Install ``AsyncioSelectorReactor`` as the default Twisted reactor.
+
+    .. deprecated:: 5.1
+
+       This function is provided for backwards compatibility; code
+       that does not require compatibility with older versions of
+       Tornado should use
+       ``twisted.internet.asyncioreactor.install()`` directly.
+
+    .. versionchanged:: 6.0.3
+
+       In Tornado 5.x and before, this function installed a reactor
+       based on the Tornado ``IOLoop``. When that reactor
+       implementation was removed in Tornado 6.0.0, this function was
+       removed as well. It was restored in Tornado 6.0.3 using the
+       ``asyncio`` reactor instead.
+
+    """
+    from twisted.internet.asyncioreactor import install
+
+    install()
+
+
 if hasattr(gen.convert_yielded, "register"):
 
     @gen.convert_yielded.register(Deferred)  # type: ignore

{"golden_diff": "diff --git a/tornado/platform/twisted.py b/tornado/platform/twisted.py\n--- a/tornado/platform/twisted.py\n+++ b/tornado/platform/twisted.py\n@@ -104,6 +104,30 @@\n         return result\n \n \n+def install() -> None:\n+    \"\"\"Install ``AsyncioSelectorReactor`` as the default Twisted reactor.\n+\n+    .. deprecated:: 5.1\n+\n+       This function is provided for backwards compatibility; code\n+       that does not require compatibility with older versions of\n+       Tornado should use\n+       ``twisted.internet.asyncioreactor.install()`` directly.\n+\n+    .. versionchanged:: 6.0.3\n+\n+       In Tornado 5.x and before, this function installed a reactor\n+       based on the Tornado ``IOLoop``. When that reactor\n+       implementation was removed in Tornado 6.0.0, this function was\n+       removed as well. It was restored in Tornado 6.0.3 using the\n+       ``asyncio`` reactor instead.\n+\n+    \"\"\"\n+    from twisted.internet.asyncioreactor import install\n+\n+    install()\n+\n+\n if hasattr(gen.convert_yielded, \"register\"):\n \n     @gen.convert_yielded.register(Deferred)  # type: ignore\n", "issue": "tornado.platform.twisted disappeared but did not explain its replacement\nMany years' worth of documentation explains that folks can do\r\n\r\n```\r\nfrom tornado.platform.twisted import install\r\nreactor = install()\r\n```\r\n\r\nI can see that in https://github.com/tornadoweb/tornado/commit/004de9c301cc4c2dae4d8f2507af1851d0c9763a#diff-77b5a8a33248ef0bcafbc1bb71e9f013 Twisted integration was removed, since we can all depend on the stdlib loop APIs.  This is great, but it also breaks a bunch of Jupyter notebooks, tutorials, etc.\r\n\r\nCould you be convinced to replace all those sprawling APIs with something like this:\r\n\r\n```python3\r\ndef install():\r\n    from twisted.internet.asyncioreactor import install\r\n    install()\r\n    from twisted.internet import reactor\r\n    reactor.startRunning()\r\n    return reactor\r\n```\r\n\r\npossibly with a `warnings.warn` explaining that users could just call these APIs directly, if that's the desired end-state?\n", "before_files": [{"content": "# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n\"\"\"Bridges between the Twisted package and Tornado.\n\"\"\"\n\nimport socket\nimport sys\n\nimport twisted.internet.abstract  # type: ignore\nimport twisted.internet.asyncioreactor  # type: ignore\nfrom twisted.internet.defer import Deferred  # type: ignore\nfrom twisted.python import failure  # type: ignore\nimport twisted.names.cache  # type: ignore\nimport twisted.names.client  # type: ignore\nimport twisted.names.hosts  # type: ignore\nimport twisted.names.resolve  # type: ignore\n\n\nfrom tornado.concurrent import Future, future_set_exc_info\nfrom tornado.escape import utf8\nfrom tornado import gen\nfrom tornado.netutil import Resolver\n\nimport typing\n\nif typing.TYPE_CHECKING:\n    from typing import Generator, Any, List, Tuple  # noqa: F401\n\n\nclass TwistedResolver(Resolver):\n    \"\"\"Twisted-based asynchronous resolver.\n\n    This is a non-blocking and non-threaded resolver.  It is\n    recommended only when threads cannot be used, since it has\n    limitations compared to the standard ``getaddrinfo``-based\n    `~tornado.netutil.Resolver` and\n    `~tornado.netutil.DefaultExecutorResolver`.  Specifically, it returns at\n    most one result, and arguments other than ``host`` and ``family``\n    are ignored.  It may fail to resolve when ``family`` is not\n    ``socket.AF_UNSPEC``.\n\n    Requires Twisted 12.1 or newer.\n\n    .. versionchanged:: 5.0\n       The ``io_loop`` argument (deprecated since version 4.1) has been removed.\n    \"\"\"\n\n    def initialize(self) -> None:\n        # partial copy of twisted.names.client.createResolver, which doesn't\n        # allow for a reactor to be passed in.\n        self.reactor = twisted.internet.asyncioreactor.AsyncioSelectorReactor()\n\n        host_resolver = twisted.names.hosts.Resolver(\"/etc/hosts\")\n        cache_resolver = twisted.names.cache.CacheResolver(reactor=self.reactor)\n        real_resolver = twisted.names.client.Resolver(\n            \"/etc/resolv.conf\", reactor=self.reactor\n        )\n        self.resolver = twisted.names.resolve.ResolverChain(\n            [host_resolver, cache_resolver, real_resolver]\n        )\n\n    @gen.coroutine\n    def resolve(\n        self, host: str, port: int, family: int = 0\n    ) -> \"Generator[Any, Any, List[Tuple[int, Any]]]\":\n        # getHostByName doesn't accept IP addresses, so if the input\n        # looks like an IP address just return it immediately.\n        if twisted.internet.abstract.isIPAddress(host):\n            resolved = host\n            resolved_family = socket.AF_INET\n        elif twisted.internet.abstract.isIPv6Address(host):\n            resolved = host\n            resolved_family = socket.AF_INET6\n        else:\n            deferred = self.resolver.getHostByName(utf8(host))\n            fut = Future()  # type: Future[Any]\n            deferred.addBoth(fut.set_result)\n            resolved = yield fut\n            if isinstance(resolved, failure.Failure):\n                try:\n                    resolved.raiseException()\n                except twisted.names.error.DomainError as e:\n                    raise IOError(e)\n            elif twisted.internet.abstract.isIPAddress(resolved):\n                resolved_family = socket.AF_INET\n            elif twisted.internet.abstract.isIPv6Address(resolved):\n                resolved_family = socket.AF_INET6\n            else:\n                resolved_family = socket.AF_UNSPEC\n        if family != socket.AF_UNSPEC and family != resolved_family:\n            raise Exception(\n                \"Requested socket family %d but got %d\" % (family, resolved_family)\n            )\n        result = [(typing.cast(int, resolved_family), (resolved, port))]\n        return result\n\n\nif hasattr(gen.convert_yielded, \"register\"):\n\n    @gen.convert_yielded.register(Deferred)  # type: ignore\n    def _(d: Deferred) -> Future:\n        f = Future()  # type: Future[Any]\n\n        def errback(failure: failure.Failure) -> None:\n            try:\n                failure.raiseException()\n                # Should never happen, but just in case\n                raise Exception(\"errback called without error\")\n            except:\n                future_set_exc_info(f, sys.exc_info())\n\n        d.addCallbacks(f.set_result, errback)\n        return f\n", "path": "tornado/platform/twisted.py"}], "after_files": [{"content": "# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n\"\"\"Bridges between the Twisted package and Tornado.\n\"\"\"\n\nimport socket\nimport sys\n\nimport twisted.internet.abstract  # type: ignore\nimport twisted.internet.asyncioreactor  # type: ignore\nfrom twisted.internet.defer import Deferred  # type: ignore\nfrom twisted.python import failure  # type: ignore\nimport twisted.names.cache  # type: ignore\nimport twisted.names.client  # type: ignore\nimport twisted.names.hosts  # type: ignore\nimport twisted.names.resolve  # type: ignore\n\n\nfrom tornado.concurrent import Future, future_set_exc_info\nfrom tornado.escape import utf8\nfrom tornado import gen\nfrom tornado.netutil import Resolver\n\nimport typing\n\nif typing.TYPE_CHECKING:\n    from typing import Generator, Any, List, Tuple  # noqa: F401\n\n\nclass TwistedResolver(Resolver):\n    \"\"\"Twisted-based asynchronous resolver.\n\n    This is a non-blocking and non-threaded resolver.  It is\n    recommended only when threads cannot be used, since it has\n    limitations compared to the standard ``getaddrinfo``-based\n    `~tornado.netutil.Resolver` and\n    `~tornado.netutil.DefaultExecutorResolver`.  Specifically, it returns at\n    most one result, and arguments other than ``host`` and ``family``\n    are ignored.  It may fail to resolve when ``family`` is not\n    ``socket.AF_UNSPEC``.\n\n    Requires Twisted 12.1 or newer.\n\n    .. versionchanged:: 5.0\n       The ``io_loop`` argument (deprecated since version 4.1) has been removed.\n    \"\"\"\n\n    def initialize(self) -> None:\n        # partial copy of twisted.names.client.createResolver, which doesn't\n        # allow for a reactor to be passed in.\n        self.reactor = twisted.internet.asyncioreactor.AsyncioSelectorReactor()\n\n        host_resolver = twisted.names.hosts.Resolver(\"/etc/hosts\")\n        cache_resolver = twisted.names.cache.CacheResolver(reactor=self.reactor)\n        real_resolver = twisted.names.client.Resolver(\n            \"/etc/resolv.conf\", reactor=self.reactor\n        )\n        self.resolver = twisted.names.resolve.ResolverChain(\n            [host_resolver, cache_resolver, real_resolver]\n        )\n\n    @gen.coroutine\n    def resolve(\n        self, host: str, port: int, family: int = 0\n    ) -> \"Generator[Any, Any, List[Tuple[int, Any]]]\":\n        # getHostByName doesn't accept IP addresses, so if the input\n        # looks like an IP address just return it immediately.\n        if twisted.internet.abstract.isIPAddress(host):\n            resolved = host\n            resolved_family = socket.AF_INET\n        elif twisted.internet.abstract.isIPv6Address(host):\n            resolved = host\n            resolved_family = socket.AF_INET6\n        else:\n            deferred = self.resolver.getHostByName(utf8(host))\n            fut = Future()  # type: Future[Any]\n            deferred.addBoth(fut.set_result)\n            resolved = yield fut\n            if isinstance(resolved, failure.Failure):\n                try:\n                    resolved.raiseException()\n                except twisted.names.error.DomainError as e:\n                    raise IOError(e)\n            elif twisted.internet.abstract.isIPAddress(resolved):\n                resolved_family = socket.AF_INET\n            elif twisted.internet.abstract.isIPv6Address(resolved):\n                resolved_family = socket.AF_INET6\n            else:\n                resolved_family = socket.AF_UNSPEC\n        if family != socket.AF_UNSPEC and family != resolved_family:\n            raise Exception(\n                \"Requested socket family %d but got %d\" % (family, resolved_family)\n            )\n        result = [(typing.cast(int, resolved_family), (resolved, port))]\n        return result\n\n\ndef install() -> None:\n    \"\"\"Install ``AsyncioSelectorReactor`` as the default Twisted reactor.\n\n    .. deprecated:: 5.1\n\n       This function is provided for backwards compatibility; code\n       that does not require compatibility with older versions of\n       Tornado should use\n       ``twisted.internet.asyncioreactor.install()`` directly.\n\n    .. versionchanged:: 6.0.3\n\n       In Tornado 5.x and before, this function installed a reactor\n       based on the Tornado ``IOLoop``. When that reactor\n       implementation was removed in Tornado 6.0.0, this function was\n       removed as well. It was restored in Tornado 6.0.3 using the\n       ``asyncio`` reactor instead.\n\n    \"\"\"\n    from twisted.internet.asyncioreactor import install\n\n    install()\n\n\nif hasattr(gen.convert_yielded, \"register\"):\n\n    @gen.convert_yielded.register(Deferred)  # type: ignore\n    def _(d: Deferred) -> Future:\n        f = Future()  # type: Future[Any]\n\n        def errback(failure: failure.Failure) -> None:\n            try:\n                failure.raiseException()\n                # Should never happen, but just in case\n                raise Exception(\"errback called without error\")\n            except:\n                future_set_exc_info(f, sys.exc_info())\n\n        d.addCallbacks(f.set_result, errback)\n        return f\n", "path": "tornado/platform/twisted.py"}]}