Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions src/klein/_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
from ._app import (
ErrorMethods,
Klein,
KleinRenderable,
KleinRouteHandler,
RouteMetadata,
)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -279,14 +298,15 @@ def processing_failed(
he = failure.value
assert isinstance(he, HTTPException)
request.setResponseCode(he.code)

resp = he.get_response({})

for header, value in resp.headers:
request.setHeader(
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]
Expand Down Expand Up @@ -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
2 changes: 1 addition & 1 deletion src/klein/test/test_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down