From 8fbc4885c51eb60541866ee80192160dc15b36b7 Mon Sep 17 00:00:00 2001 From: "H.Shay" Date: Thu, 24 Jun 2021 13:27:49 -0700 Subject: [PATCH 01/11] convert http/servlets/registerservlet.py to use aysnc/await --- sydent/http/servlets/__init__.py | 4 ++-- sydent/http/servlets/registerservlet.py | 14 ++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/sydent/http/servlets/__init__.py b/sydent/http/servlets/__init__.py index 3ecfff69..350ee846 100644 --- a/sydent/http/servlets/__init__.py +++ b/sydent/http/servlets/__init__.py @@ -162,7 +162,7 @@ def inner(self, request: Request, *args, **kwargs) -> bytes: return inner -def deferjsonwrap(f): +def asyncjsonwrap(f): def reqDone(resp: Dict[str, Any], request: Request) -> None: """ Converts the given response content into JSON and encodes it to bytes, then @@ -216,7 +216,7 @@ def inner(*args, **kwargs) -> int: """ request = args[1] - d = defer.maybeDeferred(f, *args, **kwargs) + d = defer.ensureDeferred(f(*args, **kwargs)) d.addCallback(reqDone, request) d.addErrback(reqErr, request) return server.NOT_DONE_YET diff --git a/sydent/http/servlets/registerservlet.py b/sydent/http/servlets/registerservlet.py index c0e92578..aa7f2099 100644 --- a/sydent/http/servlets/registerservlet.py +++ b/sydent/http/servlets/registerservlet.py @@ -21,9 +21,10 @@ from twisted.web.server import Request from sydent.http.httpclient import FederationHttpClient -from sydent.http.servlets import deferjsonwrap, get_args, send_cors +from sydent.http.servlets import asyncjsonwrap, get_args, send_cors from sydent.users.tokens import issueToken from sydent.util.stringutils import is_valid_matrix_server_name +from sydent.types import JsonDict if TYPE_CHECKING: from sydent.sydent import Sydent @@ -38,9 +39,8 @@ def __init__(self, syd: "Sydent") -> None: self.sydent = syd self.client = FederationHttpClient(self.sydent) - @deferjsonwrap - @defer.inlineCallbacks - def render_POST(self, request: Request) -> Generator: + @asyncjsonwrap + async def render_POST(self, request: Request) -> JsonDict: """ Register with the Identity Server """ @@ -57,8 +57,7 @@ def render_POST(self, request: Request) -> Generator: "error": "matrix_server_name must be a valid Matrix server name (IP address or hostname)", } - result = yield defer.ensureDeferred( - self.client.get_json( + result = await self.client.get_json( "matrix://%s/_matrix/federation/v1/openid/userinfo?access_token=%s" % ( matrix_server, @@ -66,7 +65,6 @@ def render_POST(self, request: Request) -> Generator: ), 1024 * 5, ) - ) if "sub" not in result: raise Exception("Invalid response from homeserver") @@ -106,7 +104,7 @@ def render_POST(self, request: Request) -> Generator: "error": "The Matrix homeserver returned a MXID belonging to another homeserver", } - tok = yield issueToken(self.sydent, user_id) + tok = issueToken(self.sydent, user_id) # XXX: `token` is correct for the spec, but we released with `access_token` # for a substantial amount of time. Serve both to make spec-compliant clients From d9895ced6f0598e3286aec7dc8059ac3022ad851 Mon Sep 17 00:00:00 2001 From: "H.Shay" Date: Thu, 24 Jun 2021 13:32:50 -0700 Subject: [PATCH 02/11] lints --- sydent/http/servlets/registerservlet.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/sydent/http/servlets/registerservlet.py b/sydent/http/servlets/registerservlet.py index aa7f2099..f87ef2cd 100644 --- a/sydent/http/servlets/registerservlet.py +++ b/sydent/http/servlets/registerservlet.py @@ -14,17 +14,16 @@ import logging import urllib -from typing import TYPE_CHECKING, Generator +from typing import TYPE_CHECKING -from twisted.internet import defer from twisted.web.resource import Resource from twisted.web.server import Request from sydent.http.httpclient import FederationHttpClient from sydent.http.servlets import asyncjsonwrap, get_args, send_cors +from sydent.types import JsonDict from sydent.users.tokens import issueToken from sydent.util.stringutils import is_valid_matrix_server_name -from sydent.types import JsonDict if TYPE_CHECKING: from sydent.sydent import Sydent @@ -58,13 +57,13 @@ async def render_POST(self, request: Request) -> JsonDict: } result = await self.client.get_json( - "matrix://%s/_matrix/federation/v1/openid/userinfo?access_token=%s" - % ( - matrix_server, - urllib.parse.quote(args["access_token"]), - ), - 1024 * 5, - ) + "matrix://%s/_matrix/federation/v1/openid/userinfo?access_token=%s" + % ( + matrix_server, + urllib.parse.quote(args["access_token"]), + ), + 1024 * 5, + ) if "sub" not in result: raise Exception("Invalid response from homeserver") From 573f73238f8cbde89ef8a581ca8cbb2ec6e6773b Mon Sep 17 00:00:00 2001 From: "H.Shay" Date: Thu, 24 Jun 2021 13:35:42 -0700 Subject: [PATCH 03/11] add changelog Signed-off-by: H.Shay --- changelog.d/372.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/372.misc diff --git a/changelog.d/372.misc b/changelog.d/372.misc new file mode 100644 index 00000000..ce3f6734 --- /dev/null +++ b/changelog.d/372.misc @@ -0,0 +1 @@ +Convert inlineCallbacks to async/await. \ No newline at end of file From 45f9977e472f673e447e64a461063e37a6c2b4bf Mon Sep 17 00:00:00 2001 From: "H.Shay" Date: Thu, 24 Jun 2021 18:35:43 -0700 Subject: [PATCH 04/11] remove callbacks --- sydent/http/servlets/__init__.py | 69 ++++++++++++-------------------- 1 file changed, 26 insertions(+), 43 deletions(-) diff --git a/sydent/http/servlets/__init__.py b/sydent/http/servlets/__init__.py index 350ee846..e551b842 100644 --- a/sydent/http/servlets/__init__.py +++ b/sydent/http/servlets/__init__.py @@ -19,7 +19,7 @@ from typing import Any, Dict, Iterable from twisted.internet import defer -from twisted.python.failure import Failure +from twisted.python import failure from twisted.web import server from twisted.web.server import Request @@ -163,45 +163,32 @@ def inner(self, request: Request, *args, **kwargs) -> bytes: def asyncjsonwrap(f): - def reqDone(resp: Dict[str, Any], request: Request) -> None: - """ - Converts the given response content into JSON and encodes it to bytes, then - writes it as the response to the given request with the right headers. - - :param resp: The response content to convert to JSON and encode. - :param request: The request to respond to. - """ - request.setHeader("Content-Type", "application/json") - request.write(dict_to_json_bytes(resp)) - request.finish() - - def reqErr(failure: Failure, request: Request) -> None: - """ - Logs the given failure. If the failure is a MatrixRestError, writes a response - using the info it contains, otherwise responds with 500 Internal Server Error. - - :param failure: The failure to process. - :param request: The request to respond to. - """ - request.setHeader("Content-Type", "application/json") - if failure.check(MatrixRestError) is not None: - request.setResponseCode(failure.value.httpStatus) - request.write( - dict_to_json_bytes( - {"errcode": failure.value.errcode, "error": failure.value.error} + async def render(f, *args, **kwargs): + request = args[1] + try: + result = await f(*args, **kwargs) + request.setHeader("Content-Type", "application/json") + request.write(dict_to_json_bytes(result)) + request.finish() + except Exception: + f = failure.Failure() + request.setHeader("Content-Type", "application/json") + if f.check(MatrixRestError) is not None: + request.setResponseCode(f.value.httpStatus) + request.write( + dict_to_json_bytes( + {"errcode": f.value.errcode, "error": f.value.error} + ) ) - ) - else: - logger.error( - "Request processing failed: %r, %s", failure, failure.getTraceback() - ) - request.setResponseCode(500) - request.write( - dict_to_json_bytes( - {"errcode": "M_UNKNOWN", "error": "Internal Server Error"} + else: + logger.error("Request processing failed: %r, %s", f, f.getTraceback()) + request.setResponseCode(500) + request.write( + dict_to_json_bytes( + {"errcode": "M_UNKNOWN", "error": "Internal Server Error"} + ) ) - ) - request.finish() + request.finish() def inner(*args, **kwargs) -> int: """ @@ -214,11 +201,7 @@ def inner(*args, **kwargs) -> int: :return: A special code to tell the servlet that the response isn't ready yet and will come later. """ - request = args[1] - - d = defer.ensureDeferred(f(*args, **kwargs)) - d.addCallback(reqDone, request) - d.addErrback(reqErr, request) + defer.ensureDeferred(render(f, *args, **kwargs)) return server.NOT_DONE_YET return inner From 78ae2d4be48cb6a95826539eb8c6c5cbfbe8e0be Mon Sep 17 00:00:00 2001 From: "H.Shay" Date: Fri, 25 Jun 2021 08:36:18 -0700 Subject: [PATCH 05/11] update changelog number --- changelog.d/373.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/373.misc diff --git a/changelog.d/373.misc b/changelog.d/373.misc new file mode 100644 index 00000000..b54257ca --- /dev/null +++ b/changelog.d/373.misc @@ -0,0 +1 @@ +Remove inlineCallbacks. \ No newline at end of file From 4ad3583e73fc257c3c47a2cd58c179c16604d247 Mon Sep 17 00:00:00 2001 From: "H.Shay" Date: Fri, 25 Jun 2021 10:35:18 -0700 Subject: [PATCH 06/11] update changelogs --- changelog.d/372.misc | 2 +- changelog.d/373.misc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog.d/372.misc b/changelog.d/372.misc index 75a61adf..db1ed62e 100644 --- a/changelog.d/372.misc +++ b/changelog.d/372.misc @@ -1 +1 @@ -Convert inlineCallbacks to async/await. +Convert `inlineCallbacks` to async/await. diff --git a/changelog.d/373.misc b/changelog.d/373.misc index b54257ca..f62e6656 100644 --- a/changelog.d/373.misc +++ b/changelog.d/373.misc @@ -1 +1 @@ -Remove inlineCallbacks. \ No newline at end of file +Convert `inlineCallbacks` to async/await. \ No newline at end of file From 784f5255f0a8604cb42671831c30a4f5a06c9dfd Mon Sep 17 00:00:00 2001 From: "H.Shay" Date: Fri, 25 Jun 2021 11:24:13 -0700 Subject: [PATCH 07/11] rewite asyncjsonwrap for clarity Signed-off-by: H.Shay --- sydent/http/servlets/__init__.py | 33 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/sydent/http/servlets/__init__.py b/sydent/http/servlets/__init__.py index e551b842..bb96e73e 100644 --- a/sydent/http/servlets/__init__.py +++ b/sydent/http/servlets/__init__.py @@ -163,31 +163,26 @@ def inner(self, request: Request, *args, **kwargs) -> bytes: def asyncjsonwrap(f): - async def render(f, *args, **kwargs): - request = args[1] + async def render(f, servlet, request, **kwargs): + request.setHeader("Content-Type", "application/json") try: - result = await f(*args, **kwargs) - request.setHeader("Content-Type", "application/json") + result = await f(servlet, request, **kwargs) request.write(dict_to_json_bytes(result)) request.finish() + except MatrixRestError as e: + request.setResponseCode(e.value.httpStatus) + request.write( + dict_to_json_bytes({"errcode": e.value.errcode, "error": e.value.error}) + ) except Exception: f = failure.Failure() - request.setHeader("Content-Type", "application/json") - if f.check(MatrixRestError) is not None: - request.setResponseCode(f.value.httpStatus) - request.write( - dict_to_json_bytes( - {"errcode": f.value.errcode, "error": f.value.error} - ) - ) - else: - logger.error("Request processing failed: %r, %s", f, f.getTraceback()) - request.setResponseCode(500) - request.write( - dict_to_json_bytes( - {"errcode": "M_UNKNOWN", "error": "Internal Server Error"} - ) + logger.error("Request processing failed: %r, %s", f, f.getTraceback()) + request.setResponseCode(500) + request.write( + dict_to_json_bytes( + {"errcode": "M_UNKNOWN", "error": "Internal Server Error"} ) + ) request.finish() def inner(*args, **kwargs) -> int: From 7969c67e681f8277332b4c7f2e6d2d912b932a65 Mon Sep 17 00:00:00 2001 From: "H.Shay" Date: Fri, 25 Jun 2021 12:05:59 -0700 Subject: [PATCH 08/11] requested changes --- sydent/http/servlets/__init__.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sydent/http/servlets/__init__.py b/sydent/http/servlets/__init__.py index bb96e73e..90db206b 100644 --- a/sydent/http/servlets/__init__.py +++ b/sydent/http/servlets/__init__.py @@ -168,11 +168,10 @@ async def render(f, servlet, request, **kwargs): try: result = await f(servlet, request, **kwargs) request.write(dict_to_json_bytes(result)) - request.finish() except MatrixRestError as e: - request.setResponseCode(e.value.httpStatus) + request.setResponseCode(e.httpStatus) request.write( - dict_to_json_bytes({"errcode": e.value.errcode, "error": e.value.error}) + dict_to_json_bytes({"errcode": e.errcode, "error": e.error}) ) except Exception: f = failure.Failure() @@ -183,7 +182,7 @@ async def render(f, servlet, request, **kwargs): {"errcode": "M_UNKNOWN", "error": "Internal Server Error"} ) ) - request.finish() + request.finish() def inner(*args, **kwargs) -> int: """ From 35f820ca055804677d97022f3e399f9a2be82cc5 Mon Sep 17 00:00:00 2001 From: "H.Shay" Date: Mon, 28 Jun 2021 10:04:44 -0700 Subject: [PATCH 09/11] fix lint fail --- sydent/http/servlets/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sydent/http/servlets/__init__.py b/sydent/http/servlets/__init__.py index 90db206b..75522908 100644 --- a/sydent/http/servlets/__init__.py +++ b/sydent/http/servlets/__init__.py @@ -170,9 +170,7 @@ async def render(f, servlet, request, **kwargs): request.write(dict_to_json_bytes(result)) except MatrixRestError as e: request.setResponseCode(e.httpStatus) - request.write( - dict_to_json_bytes({"errcode": e.errcode, "error": e.error}) - ) + request.write(dict_to_json_bytes({"errcode": e.errcode, "error": e.error})) except Exception: f = failure.Failure() logger.error("Request processing failed: %r, %s", f, f.getTraceback()) From beefbce02a2c7b05ab6b410407a2fe6e07723e88 Mon Sep 17 00:00:00 2001 From: "H.Shay" Date: Mon, 28 Jun 2021 11:02:29 -0700 Subject: [PATCH 10/11] requested changes --- sydent/http/servlets/__init__.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sydent/http/servlets/__init__.py b/sydent/http/servlets/__init__.py index 75522908..7c296654 100644 --- a/sydent/http/servlets/__init__.py +++ b/sydent/http/servlets/__init__.py @@ -163,10 +163,10 @@ def inner(self, request: Request, *args, **kwargs) -> bytes: def asyncjsonwrap(f): - async def render(f, servlet, request, **kwargs): + async def render(f, self, request: Request, **kwargs): request.setHeader("Content-Type", "application/json") try: - result = await f(servlet, request, **kwargs) + result = await f(self, request, **kwargs) request.write(dict_to_json_bytes(result)) except MatrixRestError as e: request.setResponseCode(e.httpStatus) @@ -182,11 +182,12 @@ async def render(f, servlet, request, **kwargs): ) request.finish() + @functools.wraps(f) def inner(*args, **kwargs) -> int: """ - Runs an asynchronous web handler function with the given arguments and add - reqDone and reqErr as the resulting Deferred's callbacks. + Runs an asynchronous web handler function with the given arguments. + :param f: The original function passed to the asyncjsonwrap decorator :param args: The arguments to pass to the function. :param kwargs: The keyword arguments to pass to the function. From 774018a66a38200f44399a2294e428cd1542d94c Mon Sep 17 00:00:00 2001 From: "H.Shay" Date: Tue, 29 Jun 2021 08:03:29 -0700 Subject: [PATCH 11/11] fix docstring --- sydent/http/servlets/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sydent/http/servlets/__init__.py b/sydent/http/servlets/__init__.py index 7c296654..1471d57a 100644 --- a/sydent/http/servlets/__init__.py +++ b/sydent/http/servlets/__init__.py @@ -187,7 +187,6 @@ def inner(*args, **kwargs) -> int: """ Runs an asynchronous web handler function with the given arguments. - :param f: The original function passed to the asyncjsonwrap decorator :param args: The arguments to pass to the function. :param kwargs: The keyword arguments to pass to the function.