diff --git a/src/klein/_resource.py b/src/klein/_resource.py index cd60820d..2eecf6cb 100644 --- a/src/klein/_resource.py +++ b/src/klein/_resource.py @@ -23,7 +23,6 @@ from ._app import ( ErrorMethods, Klein, - KleinRenderable, KleinRouteHandler, RouteMetadata, ) @@ -159,8 +158,27 @@ def __ne__(self, other: object) -> bool: return result return not result - def render(self, request: IRequest) -> KleinRenderable: - # Stuff we need to know for the mapper. + def render(self, request: IRequest) -> int | bytes: + """ + Render the request based on the underlying L{Klein} application, in a + multi-step process: + + 1. convert twisted input request information into something legible + to werkzeug + + 2. bind that info (URL, method, query args, etc) into a request + mapper, and look up a werkzeug endpoint (i.e.: klein + C{@route}-decorated method) to invoke + + 3. invoke that endpoint, getting something renderable + + 4. render that thing + + 5. handle any errors in lookup or rendering with declared error + handlers + + 6. render the thing that the error handler returned + """ try: ( url_scheme, @@ -231,8 +249,9 @@ def _execute() -> Deferred: def process(r: object) -> Any: """ Recursively go through r and any child Resources until something - returns an IRenderable, then render it and let the result of that - bubble back up. + returns something renderable (L{IResource}, L{IRenderable}, + L{bytes}, L{str}, or L{Iterable} of same), then render it and let + the result of that bubble back up. """ # isinstance() is faster than providedBy(), so this speeds up the # very common case of returning pre-rendered results, at the cost @@ -279,6 +298,7 @@ def processing_failed( he = failure.value assert isinstance(he, HTTPException) request.setResponseCode(he.code) + resp = he.get_response({}) for header, value in resp.headers: @@ -286,7 +306,7 @@ def processing_failed( ensure_utf8_bytes(header), ensure_utf8_bytes(value) ) - encoded = resp.iter_encoded() # type: ignore[attr-defined] + encoded = resp.iter_encoded() return succeed(ensure_utf8_bytes(b"".join(encoded))) else: request.processingFailed( # type: ignore[attr-defined] @@ -333,4 +353,4 @@ def write_response( d.addCallback(write_response) d.addErrback(log.err, _why="Unhandled Error writing response") - return server.NOT_DONE_YET # type: ignore[return-value] + return server.NOT_DONE_YET diff --git a/src/klein/test/test_resource.py b/src/klein/test/test_resource.py index 11d7ff9a..8ef5807a 100644 --- a/src/klein/test/test_resource.py +++ b/src/klein/test/test_resource.py @@ -144,7 +144,7 @@ def _render( request.finish() return succeed(None) - if result is not NOT_DONE_YET: # type: ignore[comparison-overlap] + if result is not NOT_DONE_YET: raise AssertionError("unreachable") # pragma: no cover if request.finished or not notifyFinish: # type: ignore[attr-defined]