diff --git a/changelog.d/10602.feature b/changelog.d/10602.feature
new file mode 100644
index 0000000000..ab18291a20
--- /dev/null
+++ b/changelog.d/10602.feature
@@ -0,0 +1 @@
+The Synapse manhole no longer needs coroutines to be wrapped in `defer.ensureDeferred`.
diff --git a/docs/manhole.md b/docs/manhole.md
index 37d1d7823c..db92df88dc 100644
--- a/docs/manhole.md
+++ b/docs/manhole.md
@@ -67,7 +67,7 @@ This gives a Python REPL in which `hs` gives access to the
`synapse.server.HomeServer` object - which in turn gives access to many other
parts of the process.
-Note that any call which returns a coroutine will need to be wrapped in `ensureDeferred`.
+Note that, prior to Synapse 1.41, any call which returns a coroutine will need to be wrapped in `ensureDeferred`.
As a simple example, retrieving an event from the database:
diff --git a/synapse/util/manhole.py b/synapse/util/manhole.py
index da24ba0470..522daa323d 100644
--- a/synapse/util/manhole.py
+++ b/synapse/util/manhole.py
@@ -12,6 +12,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+import inspect
import sys
import traceback
@@ -20,6 +21,7 @@ from twisted.conch.insults import insults
from twisted.conch.manhole import ColoredManhole, ManholeInterpreter
from twisted.conch.ssh.keys import Key
from twisted.cred import checkers, portal
+from twisted.internet import defer
PUBLIC_KEY = (
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDHhGATaW4KhE23+7nrH4jFx3yLq9OjaEs5"
@@ -141,3 +143,15 @@ class SynapseManholeInterpreter(ManholeInterpreter):
self.write("".join(lines))
finally:
last_tb = ei = None
+
+ def displayhook(self, obj):
+ """
+ We override the displayhook so that we automatically convert coroutines
+ into Deferreds. (Our superclass' displayhook will take care of the rest,
+ by displaying the Deferred if it's ready, or registering a callback
+ if it's not).
+ """
+ if inspect.iscoroutine(obj):
+ super().displayhook(defer.ensureDeferred(obj))
+ else:
+ super().displayhook(obj)
|